2015-09-10 3 views
4

Я изучаю семантику перемещения в C++ 11. Я написал небольшую программу для проверки поведения семантики перемещения. Но это не ведет себя так, как я ожидал, может кто-нибудь объяснить мне почему?понять поведение конструктора перемещения в этом примере

#include<iostream> 

using namespace std; 


class Vector 
{ 
public: 
    Vector() 
    { 
    cout << "empty Ctor"<<endl; 
    array = new int[10]; 
    size = 10; 
    } 

    Vector(int n) 
    { 
    array = new int[n]; 
    size = n; 
    for (int i=0; i<size; ++i) 
     array[i] = i; 
    cout << "Ctor"<<endl; 
    } 

    Vector(const Vector& v):size(v.size) 
    { 
    array = new int[size]; 
    for (int i=0; i<size; ++i) 
     array[i] = v.array[i]; 
    cout << "copy"<<endl; 
    } 

    Vector(Vector&& v):size(v.size) 
    { 
    array = v.array; 
    v.array = nullptr; 
    cout << "move"<<endl; 

    } 

    ~Vector() 
    { 
    delete array; 
    } 

private: 
    int* array; 
    int size; 

}; 

int main() { 
    Vector v(10); //print Ctor. (as expected) 
    Vector v1(std::move(v)); //print move. (as expected) 
    Vector v2(*(new Vector(2))); //print Ctor, copy. (I expect Ctor, move) 
    Vector v3(Vector(2)); //print only Ctor. (I expect Ctor, move) 

} 

Итак, почему печать не то, что я ожидал. Поскольку я думаю, что оба значения, переданные v2 и v3, равны Rvalue. И для v3, почему это печатать только CTOR без печати «движение» или «копия»

+2

В 'v3' вы получаете * copy elision *. Кстати, вам не нужны 'array' и' size'. Это не имеет значения. Вы можете и должны значительно уменьшить этот пример. – juanchopanza

+1

Это, безусловно, дублирующий вопрос. но ответ ТартанЛламы содержит полезные лакомые кусочки, такие как «но разыгрывает, что он производит lvalue», поэтому я не жалуюсь :) –

ответ

11
Vector v2(*(new Vector(2))); 

new Vector(2) является Rvalue, но разыменования производит именующее выражение, следовательно, копию, а не двигаться.

Vector v3(Vector(2)); 

Поскольку временная Vector ненужно, копия будет elided компилятором. У вашего компилятора может быть флаг, чтобы отключить копирование, чтобы вы могли видеть дополнительный ход, например. -fno-elide-constructors в GCC и Clang.

+0

Некоторая разработка этого ответа: оператор разыменования является функцией вида T & operator * (T *) и, следовательно, * p - значение l, где p имеет тип указателя. – xeonqq

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