2013-11-23 5 views
2
Line Line::operator =(Line ln) { 
     cout << "Assignment operator\n"; 
     Line temp; 
     temp.ptr = new int; 
     *temp.ptr = *(ln.ptr); 
     return temp; 
    } 

В приведенном выше фрагменте кода, конструктор копирования не вызывается, когда следующее утверждение выполняется:Почему конструктор копирования не вызывается при возврате функции?

return temp; 

Поскольку возвращение по значению, почему конструктор копирования не вызывается?

Благодаря

+2

Ошибка реализации вашего оператора: 'operator =' должен возвращать ссылку * * на '* this', а не на новый объект. –

+0

@ Konrad: Спасибо, что указали это. Итак, вы имеете в виду: this.ptr = * (ln.ptr); и вернуть * это? – Iceman

+0

Да. Весь объект 'temp' не нужен. Однако вы также не должны использовать (исходный) указатель здесь для начала. C++ обеспечивает лучшие механизмы. –

ответ

3

С вышеуказанной настройкой вполне вероятно, что компилятор завершит работу над конструктором копирования и вместо этого непосредственно создаст временный temp в том месте, где будет ожидаться возвращаемое значение. Копирование elision явно разрешено, даже если конструктор копирования имеет побочные эффекты. Однако, даже если копия завершена, конструктор копирования или перемещения все же должен быть доступен, т. Е. Потенциал копирования, не ослабляет правила доступа к соответствующему конструктору.

Если вы чувствуете, что вы абсолютно хотите иметь конструктор копирования называется, вы можете принудительно копировать конструкцию, например, путем передачи результата через тождественную функцию:

template <typename T> 
T const& identity(T const& object) { 
    return object; 
} 
// ... 
    return identity(temp); 

Обычно, вы хотите, конструктор копирования однако его можно было исключить.

+0

Как эта функция принудительно копирует? Разве это не будет просто встроено, и тогда правило as-if вступит в силу? –

+0

@ KonradRudolph: нет. Семантика различна, а копирование разрешено только в очень специфических случаях (подробнее см. В пункте 12.8 [class.copy]). «... в операторе return в функции с типом возвращаемого класса, когда выражение является имя энергонезависимый автоматический объект ... » –

+1

@KonradRudolph: Копирование разрешения является исключением из правила« как есть ». С измененным кодом вы не возвращаете локальную переменную, и поэтому освобождение больше не разрешено. –

5

Это называется копия элизия: Допустимо не сделать копию при возврате локального объекта по значению, и вместо того, чтобы локальный объект (ваш temp) строится непосредственно в вызывающем , Это допускается, даже если конструктор копирования имеет побочные эффекты.

2

Я хотел бы добавить предыдущие сообщения с замечанием о том, что даже конструктор копирования опускается при создании целевого объекта, он все равно должен быть доступен и определен. Если вы, например, произнесете свой конструктор копирования как закрытый, когда компилятор должен выпустить ошибку (кроме MS VC++, по крайней мере, 2010 года, у которой есть ошибка :))

Смежные вопросы