2013-05-30 4 views
1

Насколько я знаю, вы вызываете конструктор копирования в следующих случаях:
1 При создании экземпляра одного объекта и его инициализации значениями из другого объекта
2 При передаче объекта по значению.
3 Когда объект возвращается из функции по значению.
Я решил поставить это на тест, и я сделал эту небольшую программу, проверяя это (с сообщениями каждый раз, когда вызывается конструктор. Кажется, что это работает для первых двух случаев, но не для третьего. Я хочу узнать моя ошибка. Идеи приветствуются.Копировать конструктор не называется?

#include <iostream> 

using namespace std; 

class Circle{ 
private: 
    double* data; 
public: 
    Circle(); 
    Circle(double* set); 
    Circle(const Circle& tt1); 
    ~Circle(); 
    Circle& operator=(const Circle& tt1); 
}; 



Circle :: Circle() 
{ 
    cout << "Default constructor called" << endl; 
    data = NULL; 
} 

Circle :: Circle(double* set) 
{ 
    cout << "Set up constructor called" << endl; 
    data = new double[3]; 
    copy(set, set+3, data); 
} 

Circle :: Circle(const Circle& tt1) 
{ 
    cout << "Copy constructor called" << endl; 
    data = new double[3]; 
    copy(tt1.data, tt1.data+3, this->data); 
} 
Circle :: ~Circle() 
{ 
    cout << "Destructor called!" << endl; 
    delete[] data; 
} 

Circle& Circle :: operator=(const Circle& tt1) 
{ 
    cout << "Overloaded = called" << endl; 
    if(this != &tt1) 
    { 
     delete[] this->data; 
     this->data = new double[3]; 
     copy(tt1.data, tt1.data+3, this->data); 
    } 
    return *this; 
} 

void test2(Circle a) 
{ 

} 
Circle test3() 
{ 
    double arr [] = { 3, 5, 8, 2}; 
    Circle asd(arr); 
    cout<< "end of test 3 function" << endl; 
    return asd; 
} 

int main() 
{ 
    cout <<"-------------Test for initialization" << endl; 
    double arr [] = { 16, 2, 7}; 
    Circle z(arr); 
    Circle y = z; 
    cout << "-------------Test for pass by value" << endl; 
    test2(z); 
    cout <<"------------- Test for return value-------"<<endl; 
    Circle work = test3(); 

    cout<< "-----------Relese allocated data" << endl; 
    return 0; 
} 
+4

Вы не ошиблись. Это было просто оптимизировано. – jrok

+1

Ничего себе. Я потратил буквально пару часов, думая об этом. Ну, по крайней мере, я не забуду это сейчас! – Bloodcount

+1

@ Удовлетворение важно, чтобы вы научились этому и не забудете его. Это несколько часов, потраченных, если вы спросите меня. –

ответ

8

из Return Value Optimization копии вызова конструктора 3-й тестового случая оптимизирован прочь компилятор.

+0

Спасибо! Отмечено и узнано! – Bloodcount

+0

@Блокус всегда приветствуется! – taocp

3

практически во всех случаях компилятор не может изменить значение ваш код. Он может (и будет при оптимизации) резко изменить ваш код из того, что вы написали, в нечто более оптимальное, в то время как никогда не изменяйте наблюдаемое поведение вас r код.

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

В очень небольшом числе случаев компилятор может изменить значение вашего кода. RVO и NRVO [такая же ссылка, как указано выше] являются двумя примерами этих: компилятору разрешено исключать конструктор копирования в этих ограниченных случаях - это то, что вы видите. Компилятор должен по-прежнему проверять, что ваш конструктор копирования существует и доступен - например, он не является частным, удаленным или невозможным сгенерировать, но он не может его использовать.

По этой причине Copy Constructors [и деструкторами умозаключений] должны просто выполнять обычную вещь - как будто они уклоняются от вас, вы будете наблюдать по-разному.

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