c++ - 使用 emplace_back 避免移动构造函数调用的最佳方法?

标签 c++ c++11 c++17 emplace

我刚刚了解到 guaranteed copy elision in C++17 .根据该问题的答案:

When you do return T();, this initializes the return value of the function via a prvalue. Since that function returns T, no temporary is created; the initialization of the prvalue simply directly initializes the return value.

The thing to understand is that, since the return value is a prvalue, it is not an object yet. It is merely an initializer for an object, just like T() is.

所以我想知道,这是否适用于:

T f() {return T();}
T t = f();

所以我用 emplace_back 写了这段代码来测试它:

#include <vector>
#include <iostream>
struct BigObj{
  BigObj() = default;
  BigObj(int) { std::cout << "int ctor called" << std::endl;  }
  BigObj(const BigObj&){
    std::cout << "copy ctor called" << std::endl;
  }
  BigObj(BigObj&&){
    std::cout << "move ctor called" << std::endl;
  }
};
BigObj f(){ return BigObj(2); }
int g(){ return 2; }
int main(){
  std::vector<BigObj> v;
  v.reserve(10);
  std::cout << "emplace_back with rvalue \n";
  v.emplace_back(1+1);
  std::cout << "emplace_back with f()\n";
  v.emplace_back(f());
  std::cout << "emplace_back with g()\n";
  v.emplace_back(g());
}

这是我得到的输出(禁用复制省略):

emplace_back with rvalue 
int ctor called
emplace_back with f()
int ctor called
move ctor called
emplace_back with g()
int ctor called

似乎移动构造函数仍然被调用,即使 prvalue 直接传递给 emplace_back,我认为它可以用来直接构造一个对象而不是被用来 build 一个临时的然后移动它。

除了像 g() 函数所做的事情之外,有没有更优雅的方法来避免使用 emplace_back 调用移动构造函数?

最佳答案

It seems that the move constructor is still called even though a prvalue is passed directly into emplace_back

你认为你这样做了,但你没有将它传递给函数。你给它一个prvalue作为参数,是的,但是emplace_back接受的是一组转发references。引用必须引用一个对象,所以 temporary is materialized ,然后移动了。

使用emplace_back 的正确方法是向它传递参数以就地 初始化对象。这样您就不需要移动 vector 的元素类型(尽管您可能需要移动/复制参数)。

关于c++ - 使用 emplace_back 避免移动构造函数调用的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49749193/

相关文章:

c++ - 分而治之——买还是卖? (最大连续子数组)

C++ 类组合错误 : unrefined reference

c++ - boost.variant派生类型: cannot use copy constructor

c++ - 具有 'const' 参数重载的可变参数模板

c++ - 在这种情况下,我应该使用 lock_guard、scoped_lock 还是 unique_lock?

c++ - 将右值传递给可能不使用它的函数

c++ - 忽略几个不同的词.. c++?

c++ - 如何通过 decltype 声明迭代器的值

c++ - 如果是左值则引用,如果是右值则复制一份,即使右值持久化

c++ - C++ 中的 xvalue 是什么