Вот программа на C ++ для сравнения прямой инициализации (без =
) с копией инициализации (=
) : *
#include <iostream>
struct A {
A(int) { std::cout << "A(int)" << std::endl; }
A(A&) { std::cout << "A(A&)" << std::endl; }
A(A&&) { std::cout << "A(A&&)" << std::endl; }
};
int main() {
A a(1); // direct initialisation
A b{1}; // direct initialisation
A c = 1; // copy initialisation
A d = (1); // copy initialisation
A e = {1}; // copy initialisation
}
Компиляция программы на C ++ 14 с copy elision отключена и запуск ее с помощью следующей команды:
$ clang++ -std=c++14 -fno-elide-constructors main.cpp && ./a.out
производит следующий вывод:
A(int)
A(int)
A(int)
A(A&&)
A(int)
A(A&&)
A(int)
Почему инициализация копирования с фигурными скобками (e
) исключает конструкцию копирования / перемещения?
* Мотивация этого сравнения состояла в том, чтобы понять, как оператор возврата функции (return expression
) работает с C ++ 11. При возврате по значению можно использовать прямую инициализацию или копировать инициализацию возвращаемого значения функции. Последнее более сложно, чем инициализация копирования переменной, как здесь, потому что инициализация возвращаемого функцией значения из объекта, обозначенного expression
, включает попытку вызова конструктора перемещения типа, возвращающего функцию, сначала (даже если expression
является lvalue), прежде чем вернуться к его конструктору копирования. А начиная с C ++ 17, эта конструкция копирования / перемещения гарантированно будет исключена, если expression
является предварительным значением (обязательно оптимизация возвращаемого значения ), в то время как оно может быть исключено, если expression
является glvalue (необязательно оптимизация именованного возвращаемого значения ).