Общий ответ уже был предоставлен другими лицами, включая @ x13n. Я попытаюсь дать немного более подробное объяснение того, что действительно означает код.
Синтаксис MyObject ob = anotherMyObject;
эквивалентен MyObject obj(anotherMyObject);
. Значение: копия конструкции ob
с объекта anotherMyObject
. Компилятор всегда будет соответствовать MyObject ob = ...;
с вызовом конструктора копирования (обычно MyObject(MyObject const &)
, но может также быть MyObject(MyObject&)
, если пользователь объявляет его как таковой).
В вашем конкретном коде правая сторона не является MyObject
, поэтому она не может быть передана в качестве аргумента конструктору копирования, и компилятор попытается преобразовать этот rhs в нечто, что можно использовать с конструктором копирования MyObject
, применяя общие правила. В вашем случае, есть неявный конструктор, который принимает int
аргумента, и который может быть использован для создания временного MyObject
, поэтому компилятор переписывает код, чтобы быть:
MyObject ob(MyObject(99));
// ^^^ temporary created by the compiler to match the copy constructor
Обратите внимание, что это не то же самое, MyObject ob(99)
, но комбинация int
и конструкторов копирования, даже если общий эффект аналогичен. Если конструктор, принимающий целое число, был объявлен explicit
, тогда компилятор не смог использовать его для обеспечения преобразования, и код не смог бы скомпилировать.
В комментарии к другому ответу @ x13n указано, что это не вызов конструктора копирования, как если бы вы добавили трассировку к этому конструктору, трассировка не будет сгенерирована. Это совершенно другая проблема, когда компилятор может оптимизировать копию, создав временный адрес точно таким же адресом, что и ob
. Есть два способа проверить это, оба зависят от того, что, хотя компилятор может удалять копию, он должен придерживаться тех же ограничений. Таким образом, мы можем сделать MyObject ob(MyObject(99))
недопустимый двумя способами, либо отключение доступа к конструктору копирования, или отключить вызов конструктора с временным:
class test1 {
test1(test1 const &) {} // make the copy constructor private
public:
test1(int) {}
};
class test2 {
public:
test2(test2 &) {} // make the copy constructor take a non-const reference
// i.e. disable the use of temporaries
test2(int) {}
};
int main() {
test1 t1 = 99; // copy constructor is private in this context
test2 t2 = 99; // g++: no matching function call to test2::test2(test2)
// diagnostics will differ with other compilers
}
Нет, он не называет конструктор копирования. Добавьте `MyClass (const MyClass & asdf): a (asdf.a) {cout <<" cc call "<< endl;}` в свой код. «cc call» не будет напечатан. – x13n 2010-12-10 08:50:58
@ x13n вы правы, если мне это нравится MyClass obj (99); MyClass ob = obj; то конструктор копирования будет называться – anand 2010-12-10 08:57:51
@ x13n: Вы ошибаетесь и что @ Alien01 был прав в первую очередь. Язык указывает, что `MyClass ob = 99` эквивалентно` MyClass ob (MyClass (99)) `. То есть, компилятор создает временное с неявным конструктором и * затем * копирует его в реальный объект. Эффект, который вы видите (отсутствие вывода от вашего конструктора копирования), обусловлен оптимизацией, когда компилятор может создать временное место в том же месте, что и результирующий объект, и, таким образом, удалить копию. Чтобы проверить это, объявите конструктор копирования закрытым, и вы получите ошибку доступа в коде. – 2010-12-10 09:15:49