Я только что узнал о гарантированном копировании в 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
, который, как я думал, можно использовать для непосредственного создания объекта вместо использования для создания временного объекта с последующим его перемещением.
Есть ли более элегантный способ избежать вызова конструктора перемещения с помощью emplace_back
, кроме как делать что-то вроде того, что делает функция g()
?