32

具有通常的 Base -> Derived 层次结构,例如:

class Fruit { ... };
class Pear : Fruit { ... };
class Tomato : Fruit { ... };

std::vector<Fruit*> m_fruits;

emplace_back使用而不是有意义(例如:性能更好)push_back吗?

std::vector::emplace_back( new Pear() );
std::vector::emplace_back( new Tomato() );
4

2 回答 2

33

不要使用原始指针,std::unique_ptr像这样使用:

std::vector<std::unique_ptr<Fruit>> m_fruits;

而且由于您不能复制std::unique_ptr必须使用的构造 a emplace_back(尽管您可以使用push_backwith std::move)。

m_fruits.emplace_back(新梨());
m_fruits.emplace_back(新番茄());

编辑:

看起来如果需要重新分配内存并且无法重新分配内存,则使用std::vector<std::unique_ptr<T>>::emplace_backandnew可能会泄漏std::vector,我推荐的方法(直到 C++14 引入std::make_unique)是这样使用push_back的:

m_fruits.push_back(std::unique_ptr<Fruit>(new Pear()));
m_fruits.push_back(std::unique_ptr<Fruit>(new Tomato()));

或使用std::make_unique

m_fruits.push_back(std::make_unique<Pear>());
m_fruits.push_back(std::make_unique<Tomato>());
于 2013-04-03T10:24:34.740 回答
26

指针是标量类型,因此是文字类型,因此复制、移动和 emplace 构造(从左值或右值)都是等效的,并且通常会编译为相同的代码(标量副本)。 push_back更清楚的是您正在执行标量复制,而emplace_back应该保留用于调用非复制或移动构造函数(例如转换或多参数构造函数)的 emplace 构造。

如果您的向量应该保存std::unique_ptr<Fruit>而不是原始指针(以防止内存泄漏),那么因为您正在调用转换构造函数emplace_back会更正确。但是,如果扩展向量失败,它仍然会泄漏,所以在这种情况下你应该使用push_back(make_unique<Pear>())etc.

于 2013-04-03T10:32:18.350 回答