每当我需要将动态分配的对象添加到一个 vector 中时,我都会按照以下方式进行操作:
class Foo { ... };
vector<Foo*> v;
v.push_back(new Foo);
// do stuff with Foo in v
// delete all Foo in v
它刚刚奏效,许多其他人似乎也在做同样的事情。
今天,我了解到 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
但问题是新方法冗长乏味,而且我看没有人这样做。 (至少不在我身边……)
我应该走新路吗?
或者,我可以继续使用旧方法吗?
或者,有更好的方法吗?
最佳答案
如果您只关心此操作的异常安全性:
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.
负责释放其内容指向的对象的 vector 问题是另一回事,我相信您会得到很多关于这个的建议 ;-)
编辑:嗯,我本来是要引用标准的,但我实际上找不到必要的保证。我正在寻找的是 push_back
不会抛出,除非 (a) 它必须重新分配(我们知道它不会因为容量),或 (b) T 的构造函数抛出(我们知道它不会因为 T 是指针类型)。听起来合理,但合理!=保证。
所以,除非对这个问题有一个有益的答案:
这段代码取决于实现,没有做任何太“富有想象力”的事情。如果做不到这一点,您可以将问题的解决方案模板化:
template <typename T, typename Container>
void push_back_new(Container &c) {
auto_ptr<T> p(new T);
c.push_back(p.get());
p.release();
}
这样使用就不会太乏味了:
struct Bar : Foo { };
vector<Foo*> v;
push_back_new<Foo>(v);
push_back_new<Bar>(v);
如果它真的是一个工厂函数而不是 new
那么您可以相应地修改模板。不过,在不同的情况下传递大量不同的参数列表会很困难。
关于c++ - push_back 'dynamically allocated object' 到 vector 安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4185350/