Вызов перемещающего конструктора
Рассмотрим тест 1:
class MyClass
{
private:
string data;
public:
MyClass()
{
std::cout << "MyClass()" << std::endl;
}
MyClass(string data) : data(data)
{
std::cout << "MyClass(string data)"<< std::endl;
}
~MyClass() {}
MyClass(const MyClass& obj) // copy constr
{
std::cout << "MyClass(const MyClass& obj)" << std::endl;
}
MyClass(MyClass&& obj) // move constr
{
std::cout << "Move constructor. MyClass(MyClass&& obj)" << std::endl;
}
};
int main()
{
MyClass obj = move(MyClass("privet"));
cout << "-----------------------------" << endl;
MyClass ob = MyClass("hello");
return 0;
}
Вывод:
MyClass(string data)
Move constructor. MyClass(MyClass&& obj)
-----------------------------
MyClass(string data)
Не понимаю почему в строке MyClass ob = MyClass("hello"); срабатывает вызов только конструктора. Я ожидал увидеть вызов конструктора для временного объекта MyClass("hello"), а затем вызов конструктора перемещения для MyClass ob, который в качестве параметра принимает rvalue reference данного временного объекта, как и в случае с MyClass obj = move(MyClass("privet"));
Рассмотрим тест 2:
class A
{
public:
A()
{
std::cout << "A()" << std::endl;
}
A(const A& other)
{
std::cout << "Copy ctor\n";
}
A(A&& other)
{
std::cout << "Move ctor\n";
}
};
void first(A a) {}
void second(A&& a) {}
int main()
{
first(A{});
std::cout << "Let's call the second:\n";
second(A{});
return 0;
}
Вывод:
A()
Let's call the second:
A()
Не понимаю как тут вызываются конструкторы. Почему только по одному на функцию, должны же вызваться по конструктору для временных объектов и, в случае с функцией first создание еще одного локального объекта - копии, в случае с функцией second без понятия
Ответы (1 шт):
Вы все понимаете правильно, но компилятору разрешается оптимизировать такие вещи. Это называется copy elision. У GCC есть флаг -fno-elide-constructors, который это отключает.
Начиная с C++17 эта оптимизация стала обязательной (guaranteed copy elision), так что теперь даже A a = A(A(A())); всегда должно быть эквивалентно A a;.
Еще:
MyClass(string data) : data(data) стоит заменить на MyClass(string data) : data(std::move(data)).