C ++: какой подходящий конструктор нужно назвать: конструктор или конструктор копирования?

Код

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"?

1

Решение

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.

2

Другие решения

Выводит "constructor" потому что нужно конвертировать из 10 в ElisionTest,

Это также не печатать "copy constructor" потому что это было оптимизировано прочь (скопировать исключение). Это единственно возможная оптимизация, позволяющая изменить наблюдаемое поведение программы.

1