удаление конста в конструкторе копирования

Это то, что я сделал изначально.

class A
{   public:
A()         { std::cout << "\ndefault constructor";     }
A(const A&) { std::cout << "\ncopy constructor";        }
A(int)      { std::cout << "\nconversion constructor";  }
};

A a0;           // print default constructor
A a1(a0);       // print copy constructor       note : direct initialization
A a2 = a0;      // print copy constructor       note : copy initialization
A a3(123);      // print conversion constructor     note : direct initialization
A a4 = 123;     // print conversion constructor     note : copy initialization (create a temp object from int)

Однако, если класс A слегка изменен следующим образом (удалите const в конструкторе копирования), почему произошла ошибка компиляции для последней строки? благодарю вас

class A
{   public:
A()         { std::cout << "\ndefault constructor";     }
A(A&)       { std::cout << "\ncopy constructor";        }
A(int)      { std::cout << "\nconversion constructor";  }
};

A a0;           // print default constructor
A a1(a0);       // print copy constructor       note : direct initialization
A a2 = a0;      // print copy constructor       note : copy initialization
A a3(123);      // print conversion constructor     note : direct initialization
//A a4 = 123;   // compile error

1

Решение

A a4 = 123;

эквивалентно

A a4 = A(123); // The RHS is a temporary A object.

Это работает для первого случая, так как есть конструктор, который принимает A const& в качестве типа аргумента.

Это не работает, если тип аргумента A&, Временный объект может использоваться, когда тип аргумента A const&не когда это A&,

4

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

Для случая A a4 = 123;когда объект «а4» строится, утверждение

A a4 = 123;

разбивается компилятором как

A a4 = A(123);

В приведенном выше утверждении конструктор с одним аргументом, т.е. A(int) используется для преобразования целочисленного значения «123» во временный объект & этот временный объект копируется в объект «a4» с помощью конструктора копирования. C ++ не позволяет передавать временные объекты по неконстантной ссылке, потому что временные объекты имеют значение rvalue, которое нельзя привязать к ссылке на неконстантную.

Таким образом, в общем, если вы не передаете свой аргумент с квалификатором const, то вы не можете создавать копии const объектов.

Еще один похожий пример для лучшего понимания:

class Test
{
/* Class data members */
public:
Test(Test &t) { /* Copy data members from t*/}
Test()        { /* Initialize data members */ }
};

Test fun()
{
cout << "fun() Called\n";
Test t;
return t;
}
int main()
{
Test t1;
Test t2 = fun();  //compilation error with non-const copy constructor
return 0;
}

$g++ -o main *.cpp
main.cpp: In function ‘int main()’:
main.cpp:22:18: error: cannot bind non-const lvalue reference of type ‘Test&’ to an rvalue of type ‘Test’
Test t2 = fun();
~~~^~
main.cpp:8:4: note:   initializing argument 1 of ‘Test::Test(Test&)’
Test(Test &t) { /* Copy data members from t*/}
^~~~
1