2013-10-25 4 views
0

У меня есть некоторые проблемы с пониманием конструкторов экземпляров на C++, я надеюсь, что кто-то может мне помочь.Copy constructor - Понимание проблем

Насколько я знаю, конструктор копирования вызывается (в частности, когда-либо), когда функция возвращает экземпляр класса.

#include <iostream> 
using namespace std; 

class Test 
{ 
    int a; 
public: 
    Test(int a) : a(42) 
    {} 

    // Copy constructor 
    Test(const Test& other) 
    { 
     cout << "copy constructor" << endl; 
    } 
}; 

Test test_function() 
{ 
    Test a(3); 
    return a; 
} 

int main() 
{ 
    test_function(); 
    return 0; 
} 

Итак, если я выполняю этот код, конструктор копирования никогда не будет вызван? Зачем? И какой объект, чем возвращен?

Кроме того, если я заменить строку

test_function(); 

к

Test b = test_function(); 

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

Заранее спасибо

Edit: При смене функции на:

Test test_function() 
{ 
    Test a(3); 
    Test b(34); 

    if (4 < 2) 
     return a; 

    else 
     return b; 
} 

можно увидеть вызов конструктора копирования, так как компилятор не может использовать РВО.

+1

Это оптимизация под названием «Именованная оптимизация возвращаемого значения», для краткости NRVO. –

+0

В этом примере есть один объект Test, для просмотра copyconstructors в действии вам нужно как минимум 2 объекта. Как и тест b = test_function() –

+1

Компилятор правильно отмечает, что вы не используете возвращаемое значение (ни в одном случае), и оно оптимизирует копию. Copy elision - единственная оптимизация, которая позволяет изменять наблюдаемое поведение программы. – jrok

ответ

0

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

Во всяком случае, вы можете отключить эту оптимизацию и видеть сообщение, которое вы хотите этот переключатель компилятора (GCC):

-fno-elide-constructors 

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

0
Test test_function() 
{ 
    Test a(3); 
    return a; 
} 

Эта функция объявляет локальную копию Test и вернуть его. Компилятор увидит это, поймет, что он собирается уничтожить локальную копию при создании новой копии и просто удаляет локальную копию результата. Чтобы увидеть результат, который вы хотите, это может работать лучше:

Test test_function(const Test& t) 
{ 
    return t; 
} 

int main() 
{ 
    Test t1; 
    Test t2 = test_function(t1); 
    return 0; 
}