使用emplace_back避免移动构造函数调用的最佳方法是什么?

use*_*462 19 c++ c++11 emplace c++17

刚学会了C++ 17中保证的复制省略.根据该问题的答案:

执行return T();此操作时,将通过a初始化函数的返回值prvalue.由于该函数返回T,因此不会创建临时函数; prvalue简单的初始化直接初始化返回值.

要理解的是,由于返回值是a prvalue,它还不是一个对象.它只是一个对象的初始化器,就像T()是.

所以我想知道,这是否适用于除以下之外的任何事情:

T f() {return T();}
T t = f();
Run Code Online (Sandbox Code Playgroud)

所以我编写了这段代码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());
}
Run Code Online (Sandbox Code Playgroud)

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

emplace_back with rvalue 
int ctor called
emplace_back with f()
int ctor called
move ctor called
emplace_back with g()
int ctor called
Run Code Online (Sandbox Code Playgroud)

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

是否有更优雅的方法来避免移动构造函数调用而emplace_back不是执行类似g()函数的操作?

Sto*_*ica 22

即使prvalue直接传递给emplace_back,似乎仍然会调用move构造函数

你觉得你这样做,但你不把它传递的功能.你给它一个prvalue作为参数,是的,但emplace_back接受的是一包转发引用.引用必须引用一个对象,因此临时具体化并移动.

使用正确的方法emplace_back是通过它的参数初始化对象到位.这样您就不需要移动向量的元素类型(尽管您可能需要移动/复制参数).

  • @ user2108462 - 是的.绑定到引用是临时实现的地方.它必须发生,所以我们得到被引用的对象. (4认同)