【问题标题】:emplace_back() does not behave as expectedemplace_back() 未按预期运行
【发布时间】:2014-07-19 20:24:22
【问题描述】:

我编写了一个简单的程序来在标准库容器中就地创建对象。这是我写的:

#include <vector>
#include <iostream>

class AB
{
public:
   explicit AB(int n);
   AB(const AB& other) = delete;
   AB(AB&& other);
   AB& operator=(const AB& other) = delete;
   AB& operator=(AB&& other) = default;
private:
   int i;
};

AB::AB(int n): i( n )
{
   std::cout << "Object created." << std::endl;
};

AB::AB(AB&& other): i( std::move(other.i) )
{
   std::cout << "Object moved." << std::endl;
};

int main()
{
   std::vector< AB > v;
   v.emplace_back(1);
   v.emplace_back(2);
   v.emplace_back(3);
};

我用 g++(4.8.2 版)编译它。运行输出后,我得到:

Object created.
Object created.
Object moved.
Object created.
Object moved.
Object moved.

但我期待的是这样的:

Object created.
Object created.
Object created.

我认为安置的全部意义在于摆脱移动构造函数调用。 AB类有什么要求没有满足吗?

感谢您的帮助。

【问题讨论】:

  • +1 很高兴看到一个清晰的问题,包含所有必要的信息和一个独立的工作代码示例。不幸的是,这几天是个例外。
  • 注意:如果你不删除复制构造函数,那么你的对象就是copied。这是因为除非移动构造函数被标记为noexcept,否则vector 在重新分配元素时将更喜欢使用非破坏性复制构造函数。因此... 将移动构造函数标记为noexcept :)

标签: c++ c++11 g++ std


【解决方案1】:

问题是当您添加更多元素时,您的矢量正在调整大小,从而导致额外的移动。如果一开始就预留了足够的容量,就会得到预期的结果:

   std::vector< AB > v;
   v.reserve(3);
   v.emplace_back(1);
   v.emplace_back(2);
   v.emplace_back(3);

给予

Object created.
Object created.
Object created.

在 gcc 4.8.2 上。请注意,您可以通过查看 v.capacity() 来跟踪原始代码中向量的增长。

【讨论】:

  • 感谢您的回答。这对我的理解很有帮助。
【解决方案2】:

位置的重点是摆脱 COPY 构造函数调用。由于矢量已满时调整大小,它可能正在移动对象。移动一个物体是好的。复制一个对象很昂贵。

【讨论】:

    猜你喜欢
    • 2014-11-12
    • 1970-01-01
    • 2020-06-28
    • 2012-02-18
    • 2018-01-18
    • 2012-06-14
    • 2019-03-03
    • 2012-09-21
    • 2014-12-08
    相关资源
    最近更新 更多