我应该使用C++11的emplace_back与指针containters吗?

问题描述 投票:22回答:2

有一个通常的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() );
c++ c++11 smart-pointers
2个回答
21
投票

指针是标量类型,因此是文字类型,所以复制、移动和置换构造(从lvalue或rvalue)都是等价的,通常会编译成相同的代码(标量拷贝)。 push_back 更清楚的是,你正在执行一个标量拷贝,而 emplace_back 应该保留给调用非复制或移动构造函数的emplace构造(例如converting或多参数构造函数)。

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


26
投票

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

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

由于你不能复制构建一个 std::unique_ptr 你必须使用 emplace_back (尽管你可以使用 push_backstd::move).

m_fruits.emplace_back(new Pear());m_fruits.emplace_back(new Tomato())。

编辑。

看来,使用 std::vector<std::unique_ptr<T>>::emplace_backnew 泄漏,如果 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>());
© www.soinside.com 2019 - 2024. All rights reserved.