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

Best way to use emplace_back to avoid move constructor call?

本文关键字:函数调用 最佳 方法 移动 emplace back 使用      更新时间:2023-10-16

我刚刚在 C++17 中了解了保证复制省略。根据对这个问题的回答:

当你执行return T();时,这将初始化 通过prvalue功能。由于该函数返回 T,因此没有临时 创建;prvalue的初始化只是直接初始化 返回值。

要理解的是,由于返回值是一个prvalue, 它还不是一个对象。它只是一个对象的初始值设定项, 就像T()一样。

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

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中,仍然调用移动构造函数,我认为它可以用来直接构造一个对象,而不是用来构造一个临时然后移动它。

除了执行类似于g()函数所做的事情之外,有没有一种更优雅的方法可以避免使用emplace_back进行移动构造函数调用?

似乎即使将 prvalue 直接传递到 emplace_back 中,仍然调用移动构造函数

你认为你这样做了,但你没有把它传递到函数中。你给它一个 prvalue 作为参数,是的,但emplace_back接受的是一包转发引用。引用必须引用对象,因此临时被具体化并移动。

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