2013-05-04 2 views
7

Как раз тогда, когда я думал, что я как-то понимаю ссылку на rvalue, я столкнулся с этой проблемой. Код, вероятно, излишне длинный, но идея довольно проста. Существует функция main() и returnRValueRef().Как работает обратная ссылка rvalue?

#include <iostream> 

#define NV(x) "[" << #x << "=" << (x) << "]" 
#define log(x) cout << __FILE__ << ":" << __LINE__ << " " << x << endl 

using namespace std; 

class AClass { 
public: 
    int a_; 

    AClass() : a_(0) { 
    log("inside default constructor"); 
    } 
    AClass(int aa) : a_(aa) { 
    log("inside constructor"); 
    } 
    int getInt() const { 
    return a_; 
    } 
    void setInt(int a) { 
    a_ = a; 
    } 

    AClass(AClass const & other) : a_(other.a_) { 
    log("inside copy constructor"); 
    } 

    AClass & operator=(AClass const & rhs) { 
    log("inside assignment operator" << "left value" << NV(a_) << "right value" << NV(rhs.a_)); 
    a_ = rhs.a_; 
    return *this; 
    } 

    AClass & operator=(AClass && rhs) { 
    log("inside assignment operator (rvalue ref)" << "left" << NV(a_) << "right" << NV(rhs.a_)); 
    a_ = rhs.a_; 
    return *this; 
    } 
}; 

AClass && returnRValueRef() { 
    AClass a1(4); 
    return move(a1); 
} 

int main() { 
    AClass a; 
    a = returnRValueRef(); 
} 

Хорошо, я ожидал бы этот код первой страницы «внутри конструктора по умолчанию» (для), затем «внутри конструктора» (для a1), а затем оператор присваивания сообщение с rhs.a_ = 4. Но выход

testcpp/return_rvalue_ref.cpp:14 inside default constructor 
testcpp/return_rvalue_ref.cpp:17 inside constructor 
testcpp/return_rvalue_ref.cpp:39 inside assignment operator (rvalue ref)left[a_=0]right[rhs.a_=0] 

Может кто-нибудь объяснить, почему последнюю строку в выходных отпечатков right[rhs.a_=0] вместо right[rhs.a_=4]? Я думал, что move() просто делает lvalue в rvalue без изменения его содержимого. Но я явно чего-то пропускаю.

Большое спасибо за помощь. :-)

Редактировать: Я думаю, что знаю, что может быть. Может быть деструктором для a1 в функции returnRValueRef() вызывается, когда он выходит из области видимости (даже если он был преобразован в rvalue), и после этого ячейка памяти для a1 (или rvalue reference для нее) содержит неопределенные вещи! Не уверен, что это то, что происходит, но кажется правдоподобным.

ответ

18

Ссылка rvalue по-прежнему является ссылкой. В вашем случае вы ссылаетесь на локальную переменную, которая была разрушена. Поэтому для доступа к членам существует неопределенное поведение. То, что вы хотите сделать, это вернуть объект:

AClass returnRValueRef() { 
    AClass a1(4); 
    return move(a1); 
} 

Однако движение происходит автоматически с помощью локальной переменной, так что вам действительно нужно только сделать это:

AClass returnRValueRef() { 
    AClass a1(4); 
    return a1; 
} 
+0

Спасибо за ваш комментарий. Пока вы добавили свой комментарий, я также отредактировал этот вопрос, и кажется, что вы сказали, что проблема. Благодарю. (Извините, я не могу поддержать ваш ответ, хотя слишком мало очков.) –

+0

@YogeshwerSharma: просто согласиться было бы здорово, спасибо! –

+0

Есть ли пример, где полезно использовать ссылку rvalue? Кажется, не так ли? :( –

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