Код
class ElisionTest
{
public:
int n;
// ElisionTest(ElisionTest& other): n(other.n) {cout<<"copy constructor"<<endl;}
ElisionTest(int n): n(n) {cout<<"constructor"<<endl;}
};
int main(int argc, char const *argv[])
{
ElisionTest et = 10;
}
печать "constructor"
и это нормально. Теперь, когда я раскомментирую конструктор копирования, я получаю ошибку времени компиляции:
cpp_test.cpp: In function 'int main(int, const char**)':
cpp_test.cpp:140:19: error: no matching function for call to 'ElisionTest::ElisionTest(ElisionTest)'
cpp_test.cpp:140:19: note: candidates are:
cpp_test.cpp:135:2: note: ElisionTest::ElisionTest(int)
cpp_test.cpp:135:2: note: no known conversion for argument 1 from 'ElisionTest' to 'int'
cpp_test.cpp:134:2: note: ElisionTest::ElisionTest(ElisionTest&)
cpp_test.cpp:134:2: note: no known conversion for argument 1 from 'ElisionTest' to 'ElisionTest& {aka ElisionTest&}'
Что, вероятно, продолжает показывать, что здесь конструктор копирования будет вызываться с временным ElisionTest(10)
, А так как вы не можете иметь неконстантную ссылку на временную переменную, аргумент конструктора копирования становится const&
должен устранить ошибку.
Но если я изменю конструктор копирования, чтобы взять const ElisionTest&
вместо ElisionTest&
нет ошибки и вывод "constructor"
снова. Почему это не печатать "copy constructor"
?
ElisionTest(ElisionTest& other);
Конструктор с этой подписью позволяет инициализировать ElisionTest
экземпляр через lvalue. Когда вы делаете это:
ElisionTest et = 10;
Это создаст экземпляр ElisionTest
из временного. Ваш код эквивалентен:
ElisionTest et = ElisionTest(10);
Это вызовет ваш конструктор, который принимает неконстантную ссылку и инициализирует et
с этим. Но неконстантная ссылка не может быть привязана к временной. Вот почему нам нужно будет добавить const
к вашему конструктору копирования, чтобы он мог поддерживать как lvalues, так и rvalues:
ElisionTest(ElisionTest const& other);
// ^^^^^
Причина, по которой вы не видите результатов, заключается в том, что копирования элизия. Компилятор может опустить вызов конструктора копирования / перемещения. В GCC вы можете использовать -fno-elide-constructors
отключить копирование elision.
Выводит "constructor"
потому что нужно конвертировать из 10
в ElisionTest
,
Это также не печатать "copy constructor"
потому что это было оптимизировано прочь (скопировать исключение). Это единственно возможная оптимизация, позволяющая изменить наблюдаемое поведение программы.