将RVO对象传递到std::vector::template_back

Pass RVO object to std::vector::emplace_back

本文关键字:vector template back std RVO 对象      更新时间:2023-10-16

考虑以下数组:

std::vector<Foo> arr;
arr.emplace_back(calculate_foo());

emplace_back受益于消除临时对象,因为它的参数在新构造的元素上传递到位(因此这里的template_back将触发移动或复制构造函数(Foo(foo)

当然,上面的代码在calculate_foo中创建了一个临时对象,然后根据Foo的构造函数将其复制或移动到新数组中。

有没有机会加快速度并消除临时对象?

您无法避免使用emplace_backFoo的构造函数创建临时参数。如果使用类型为Foo的参数,则该参数是将传递给模板对象的构造函数的临时对象。在这种情况下,push_back将同样有效。

要真正利用定位,您的类型需要有一个构造函数,它接受一些轻量级参数,可以用来构造更昂贵的对象。这样,只有临时对象才是轻量级对象。为了直接从返回值中进行模板设置,该构造函数只能接受一个参数。

示例:

struct ExpensiveMove {
explicit ExpensiveMove(double d) {
std::cout << "constructn";
std::fill(arr.begin(), arr.end(), d);
}
ExpensiveMove(const ExpensiveMove&) { std::cout << "expensive copyn"; }
ExpensiveMove(ExpensiveMove&&) { std::cout << "expensive moven"; }
ExpensiveMove& operator=(const ExpensiveMove&) { std::cout << "expensive copy assn"; return *this; }
ExpensiveMove& operator=(ExpensiveMove&&) { std::cout << "expensive move assn"; return *this; }
std::array<double, 1024> arr;
};
double calculate()
{
return 4.2;
}
int main() {
std::vector<ExpensiveMove> arr;
arr.emplace_back(calculate());
}

本例中没有ExpensiveMove类型的临时存储器。有一个临时替身,这并不重要。