2013-08-15 6 views
4
Class Cents(){ 
int m_val; 
public: 
    Cents(int x=0){ cout<<"Constructor";} 
    Cents(const Cents& src){ cout<<"Copy constructor"} 
    Cents Add(int val){m_val=val; return *this} // --->(1) 
} 

Предположим, у меня есть Cents object obj и звоню obj.Add()Почему конструктор копирования вызывается только тогда, когда мы возвращаем * это?

Теперь выход будет

Конструктор
Copy конструктор

Так что мое предположение было здесь по возвращении *this в (1) мы копируем значение объекта *this в новый временный объект Cents obj ЭСТ. Вот почему вызывается конструктор копирования.

Теперь, если я линия (1) с

Cents Add(int val){ Cents temp;return temp;} // --->(2) 

заменить только выход

Конструктор

Почему конструктор копирования не вызывается? Является ли мое предположение о строке (1) неправильным?

+0

Предоставьте код, который использует ваш класс 'Cents', я не вижу никакого вызова конструктора в вашем фрагменте кода. – SpongeBobFan

+0

@SpongeBobFan: пример - функция« Добавить », вторая версия, которая (в принципе) возвращает копия локальной переменной 'temp'. –

+0

@SpongeBobFan> Ниже приведен фрагмент кода. Часть создания объекта. Я только что сказал в словах. Я думаю, это почему вы не могли понять. Below - это несколько частей кода. Для второго программного кода PLS замените строку (1) на эта строка Cents Add (int val) {Cents temp; return temp;} .Rest кода такой же.Класс Cents() { int m_val; public: Cents (int x = 0) {cout << "Constructor";} Cents (const Cents & src) {cout << "Конструктор копирования"} Cents Add (int val) {m_val = val; return * this} // ---> (1) } int main() {Cents obj; obj.Add (10));} – Poorvi

ответ

11

Это оптимизация, известная как копия elision, иногда называемая «(N) RVO» (для «(названной) оптимизации возвращаемого значения») теми, кто любит акронимы.

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

Возврат временной или локальной переменной из одной из этих ситуаций. Вместо того, чтобы создавать temp в стеке стека функции, а затем копировать его в вызывающий, программа может вместо этого создавать его непосредственно в кадре вызывающего абонента.

Когда вы возвращаете *this, копия не может быть удалена, так как *this имеет срок службы вне функции. С точки зрения абонента зрения, будет два объекта, поэтому программа должна фактически сделать копию:

Cents original; 
Cents copy = original.Add(42); 

// "copy" and "original" both exist: the object must have been copied. 

Для получения подробной информации о которых операции могут быть Опущенные этой оптимизации, см C++ 11 Standard, 12,8/31.

+0

> Значит, вы хотели сказать, что техника копирования ellision не применяется для Cents obj = * this.and for Cents obj = некоторый временный объект, компилятор C++ позволит копировать ellision. Фактически я не понял, что вы подразумеваете под утверждением «Когда вы возвращаете * это, копия не может быть удалена». И если вы не возражайте, не могли бы вы рассказать в миряне langauage.Потому что это заявление является точным андерсером на мой вопрос. – Poorvi

+0

@Poorvi: Я добавил немного больше о том, почему 'return * this' не может быть отменено. Функция должна создать второй объект, отдельно от '* this', поэтому он действительно должен быть скопирован. –

+0

> ooh это означает, так как потому, что * у этого есть жизнь даже после этой функции добавления, компилятор не пропускает * this, поэтому он копирует * это значение во временный объект Cents, такой как {возвращающий временный объект Cents здесь} Add() = * this.While, в другом случае, мы копируем локальную временную точку Cents для временного объекта Cents. Так что компилятор вызывает конструктор для оператора tements Cents и инициализирует его напрямую .hence omitting callor constructor, т. е. поскольку поскольку оба являются временными переменными, просто делая вызов конструктора thats it.Am я получил это правильно? – Poorvi

3

Это происходит потому, что большинство компиляторов выполняют Return Value Optimization (aka RVO), чтобы сэкономить на копировании.

+0

> Спасибо Влад – Poorvi

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