2016-04-19 5 views
1

Я хочу знать, что здесь происходит:конструктор копирования не вызывается при возврате зЬй :: вектор

class Test { 
public: 
    Test() { std::cout << "Constructor" << std::endl; } 
    Test(const Test &) { std::cout << "Copy" << std::endl; } 
    Test(const Test &&) { std::cout << "Move" << std::endl; } 
    ~Test() { std::cout << "Destructor" << std::endl; } 
}; 
std::vector<Test> getTestVektor() { 
    std::vector<Test> TestVektor(1); 
    return TestVektor; 
} 
Test getTest() { 
    Test TestVariable; 
    return TestVariable; 
} 

int main() { 
    { 
     std::vector<Test> TestVektor = getTestVektor(); 
    } 
    std::cout << std::endl; 
    { 
     Test TestVarible = getTest(); 
    } 
    std::cout << std::endl; 
    { 
     std::vector<Test> TestVektor(1); 
     std::vector<Test> TestVektor2 = TestVektor; 
    } 
    return 0; 
} 

скомпилирован с VisualStudio 2012:

Constructor 
Destructor 

Constructor 
Move 
Destructor 
Destructor 

Constructor 
Copy 
Destructor 
Destructor 

Можно было бы объяснить первый случай с копией элизии , Но это противоречит второму случаю, когда был вызван конструктор перемещения.

Другим объяснением было бы то, что std :: vector в функции освобождает его содержимое и передает его второму std :: vector, поэтому вызов конструктора копирования отсутствует. Но третий случай показывает, что это не так.

Итак, что здесь происходит? Или это просто мази компилятор opitimization?

+0

Знакомый с «Именованная оптимизация возвращаемого значения»?(Я согласен, что он должен применяться и в случае № 2) –

+0

Где ваши операторы присваивания копий/перемещений? – xaxxon

+0

@BenVoigt Да. Видимо, конструктор перемещения вектора является важным моментом ... – Corylus

ответ

2

Первый случай (в худшем случае) перемещает вектор (поэтому просто переносит внутренний указатель, без копирования/перемещения Test).

3-й случай делает копию вектора, вы должны сделать следующее, чтобы переместить его вместо копирования:

{ 
    std::vector<Test> TestVektor(1); 
    std::vector<Test> TestVektor2 = std::move(TestVektor); 
} 
0

Можно было бы объяснить первый случай с копией элизии.

TestVektor был перемещен по временному вектору, который был возвращен с getTestVektor. Один, оба или ни один из ходов, возможно, были исключены.

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

Копирование/перемещение исключений не является обязательным. Он может использоваться как для возврата с getTest, так и для инициализации копии TestVarible, но он не использовался для одного из них.

Версии как GCC, так и Clang, которые я тестировал, лишили обоих.

Другое объяснение было бы, что станд :: вектор в функции отпускает ее содержимое и передает его на второй станд :: вектор

Это именно то, что этот шаг конструктор std::vector делает.

Но третий случай выполняет копирование, а не конструкцию перемещения.

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

0

FYI выход из лязга, с -O2:

Constructor 
Destructor 

Constructor 
Destructor 

Constructor 
Copy 
Destructor 
Destructor 

Почему Visual Studio будет вызывать движение в случае 2 является для меня загадкой. Вы отключили оптимизацию?

+0

Изменено/O2 и получено то же самое ;-) – Corylus

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