【问题标题】:multiple emplace_back calling copy constructor additionally多个 emplace_back 额外调用复制构造函数
【发布时间】:2018-03-26 17:27:40
【问题描述】:

考虑下面的例子:

#include <iostream>
#include <vector>

class S {
public:
  S() { puts("S()"); }
  S(int) { puts("S(int)"); }
  ~S() { puts("~S()"); }
  S(const S &) { puts("S(const S&)"); }
  S(S &&) { puts("S&&"); }
  const S &operator=(const S &s) {
    puts("=");
    return s;
  }
  S &operator=(S &&s) {
    puts("Move =");
    return s;
  }
};

int main() {
  std::vector<S> s;
  s.emplace_back();
  s.emplace_back(6);
}

O/p:

S()
S(int)
S(const S&)
~S()
~S()
~S()

当只有一个元素是emplaced_back 时,constructor/destructor pair 只被调用一次。但是当有多个emplace_back(如s.emplace_back(6);)时,也会调用copy constructor。为什么这种行为差异? emplace_back 还存在副本吗?

【问题讨论】:

    标签: c++ c++11 copy-constructor emplace


    【解决方案1】:

    考虑到std::vector 有时会扩大其分配区域(当您添加许多元素时)并且必须将旧值复制到新位置。这会导致复制构造函数的调用。

    您可以拨打reserve()

    std::vector<S> s;
    s.reserve(20);
    s.emplace_back();
    s.emplace_back(6);
    

    要说s向量必须保留更大的内存区域以避免元素的重定位。

    【讨论】:

    • 调整大小时不应该使用move构造函数吗?
    • @TobySpeight 移动构造函数只有在标记为noexcept时才允许调用。
    • 啊,是的;我忘记了。
    • @TobySpeight - 好问题;请参阅 Sombrero Chicken 的评论和 Liliscent 的回答(我承认我不知道)。
    • @SombreroChicken - 感谢您的编辑更正:-)
    【解决方案2】:

    这是因为按照@max66 的解释发生了重新分配。至于为什么调用的是拷贝构造函数,是因为你的移动构造函数不是noexcept

    改成这样:

    S(S &&) noexcept { puts("S&&"); }
    

    然后就是调用的移动构造函数了。

    【讨论】:

    • 添加noexcept 来移动ctor(没有reserve)在构造方面没有任何区别。只有复制构造函数被移动构造函数替换。
    • @Sitesh nothrow_move_constructible 是std::vector重新分配中调用move构造函数的要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多