upr*_*ser 6 c++ vector exception-safe
每当我需要将动态分配的对象添加到向量中时,我一直在做以下方式:
class Foo { ... };
vector<Foo*> v;
v.push_back(new Foo);
// do stuff with Foo in v
// delete all Foo in v
Run Code Online (Sandbox Code Playgroud)
它只是工作,许多其他人似乎做同样的事情.
今天,我学会了vector :: push_back可以抛出异常.这意味着上面的代码不是异常安全的.:-(所以我提出了一个解决方案:
class Foo { ... };
vector<Foo*> v;
auto_ptr<Foo> p(new Foo);
v.push_back(p.get());
p.release();
// do stuff with Foo in v
// delete all Foo in v
Run Code Online (Sandbox Code Playgroud)
但问题是新的方式冗长乏味,我看到没有人这样做.(至少不在我身边......)
我应该采用新的方式吗?
或者,我可以坚持旧的方式吗?
或者,有更好的方法吗?
CB *_*ley 11
你的新方式更安全,但有理由不在其他任何地方看到它.
一个vector指针只拥有指针,它不表达指向的对象的所有权.您实际上是将所有权释放给不"需要"所有权的对象.
大多数人会使用vector的shared_ptr正确表达的所有权或使用类似boost::ptr_vector.这delete两者中的任何一个都意味着您不必显式地存储您正在存储指针的对象,这些对象容易出错并且在程序的其他位置可能异常"危险".
编辑:您仍需要非常小心插入ptr_vector.不幸的是,push_back采用原始指针提供了强有力的保证,这意味着插入成功或(有效)没有任何反应,因此传入的对象既不被接管也不被破坏.采用智能指针取值的版本定义为.release()在调用强保证版本之前调用,这实际上意味着它可以泄漏.
使用vector的shared_ptr一起make_shared更容易正确地使用.
Ste*_*sop 11
如果您关心的只是此操作的异常安全:
v.reserve(v.size()+1); // reserve can throw, but that doesn't matter
v.push_back(new Foo); // new can throw, that doesn't matter either.
Run Code Online (Sandbox Code Playgroud)
负责释放其内容所指向的对象的向量问题是一个单独的问题,我相信你会得到很多关于它的建议;-)
编辑:嗯,我打算引用标准,但实际上我找不到必要的保证.我正在寻找的是push_back除非(a)它必须重新分配(我们知道它不会因为容量),或者(b)T投掷的构造函数(我们知道它赢了),所以不会抛出t因为T是指针类型).听起来合理,但合理!保证.
所以,除非在这个问题上有一个有益的答案:
是否允许std :: vector :: push_back因重新分配或构造失败以外的任何原因而抛出?
这段代码取决于实现没有做太"富有想象力"的事情.如果做不到这一点,你的问题解决方案可能会被模糊起来:
template <typename T, typename Container>
void push_back_new(Container &c) {
auto_ptr<T> p(new T);
c.push_back(p.get());
p.release();
}
Run Code Online (Sandbox Code Playgroud)
然后使用不是太乏味:
struct Bar : Foo { };
vector<Foo*> v;
push_back_new<Foo>(v);
push_back_new<Bar>(v);
Run Code Online (Sandbox Code Playgroud)
如果它真的是工厂功能而不是new那么你可以相应地修改模板.但是,在不同的情况下传递许多不同的参数列表将是困难的.
| 归档时间: |
|
| 查看次数: |
6008 次 |
| 最近记录: |