如何在没有 emplace_back() 的情况下将具有昂贵 dtor 的对象添加到向量中

How to add object with expensive dtor to vector without emplace_back()

我有一个对象 RenderBuffer,它创建一个 OpenGL 缓冲区作为其构造函数的一部分,并在其析构函数中销毁它。这是一项非常昂贵的手术。此对象没有默认构造函数,因此通常将其放入初始化列表或推入向量的后面(如果有很多):

Window::Window(Renderer & render)
    : m_renderBuffer(render) // sometimes looks like this
{
    m_multipleBuffer.push_back(RenderBuffer(render)) // othertimes can look like this
}

后一个带有向量的实例导致析构函数被调用,从而导致问题。

我正在使用 VS2010,它缺少 emplace_back() 来完成这项工作。我能做什么?我应该放弃 RAII 类型的编码风格并给我的 classes 一个 init(...) 方法吗?有没有办法让它与复制构造函数一起工作?如果有的话,仅仅使用初始化方法是否值得付出努力(为每个 class 移动构造函数会有很多样板文件)?

考虑使用指向对象的智能指针向量。例如:

vector<shared_ptr<RenderBuffer> >  m_multipleBuffer;

当然,这意味着当您需要实际的 RenderBuffer 时,您必须取消引用指针,这可能会或可能不会实用,具体取决于您程序的其余部分,但如果它 实际可以避免RenderBuffer不必要的拷贝构造和破坏。

请注意,复制构造函数也可能是一项昂贵的操作,除非 RenderBuffer 被设计为共享底层 OpenGL 缓冲区。

您可以简单地提供您自己的移动构造函数版本。例如,您可以提供一个带有附加 "move" 标志的构造函数,当为设置了此标志的对象调用复制构造函数时,它只执行移动而不是复制。

Bjarne Stroustrup 在 his keynote 在 Going Native 2012 中描述了这项技术,当时被问及 C++ 开发人员如何在 C++11 之前实现移动。

此外,虽然我没有使用过这个特定的库,但有一个 Boost.Move 可以模拟 C++03 编译器的移动语义。 Movable 类 获得特殊的移动构造函数和移动赋值运算符,它们通过具有 BOOST_RV_REF(T) 参数来区分,并使用 T a(boost::move(b))T a = boost::move(b).

调用