我刚刚了解了guaranteed copy elision in C++17。根据对该问题的回答:



所以我想知道,此功能除以下用途外是否有用:

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,似乎仍会调用move构造函数,我认为这可以用于直接构造对象,而不是用于构造临时对象然后移动它。

除了执行类似emplace_back函数的操作之外,还有没有其他更优雅的方法来避免使用g()调用move构造函数?

最佳答案



您以为可以,但是不会将其传递给函数。您给它一个prvalue作为参数,是的,但是emplace_back接受的是一包转发引用的包。引用必须引用一个对象,即temporary is materialized,并已移动。

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

07-24 09:44
查看更多