2013-05-04 33 views
7

Ngay khi tôi nghĩ tôi hiểu được tham chiếu rvalue, tôi đã gặp phải vấn đề này. Mã có lẽ không cần thiết lâu, nhưng ý tưởng khá đơn giản. Có một hàm main() và hàm returnRValueRef().Trả lại bằng cách tham khảo rvalue như thế nào?

#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(); 
} 

Được rồi, tôi mong chờ mã này để in đầu tiên "bên trong constructor mặc định" (dành cho), sau đó "bên trong constructor" (ví a1), và sau đó nhắn toán tử gán với rhs.a_ = 4. Nhưng đầu ra là

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] 

ai đó có thể giải thích lý do tại sao dòng cuối cùng trong các bản in đầu ra right[rhs.a_=0] thay vì right[rhs.a_=4]? Tôi nghĩ rằng di chuyển() chỉ làm cho lvalue thành rvalue mà không thay đổi nội dung của nó. Nhưng tôi rõ ràng thiếu cái gì đó.

Cảm ơn bạn rất nhiều vì đã giúp đỡ bạn. :-)

Chỉnh sửa: Tôi nghĩ tôi biết điều gì có thể xảy ra. Có thể là destructor cho a1 trong hàm returnRValueRef() đang được gọi khi nó nằm ngoài phạm vi (ngay cả khi nó được chuyển thành rvalue), và sau đó vị trí bộ nhớ cho a1 (hoặc tham chiếu rvalue cho nó) chứa các công cụ không xác định! Không chắc chắn nếu đó là những gì đang xảy ra, nhưng có vẻ hợp lý.

Trả lời

18

Tham chiếu rvalue vẫn là tham chiếu. Trong trường hợp của bạn, bạn đang tham chiếu biến cục bộ đã bị hủy. Do đó nó là hành vi không xác định để truy cập các thành viên. Những gì bạn muốn làm là để trả lại đối tượng:

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

Tuy nhiên, một động thái sẽ xảy ra tự động với một biến địa phương, vì vậy bạn thực sự chỉ cần làm điều này:

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

Cám ơn nhận xét của bạn. Trong khi bạn đã thêm nhận xét của mình, tôi cũng đã chỉnh sửa câu hỏi và dường như điều bạn nói là vấn đề. Cảm ơn. (Xin lỗi, tôi không thể upvote câu trả lời của bạn mặc dù, quá ít điểm.) –

+0

@YogeshwerSharma: chỉ là một chấp nhận sẽ là tuyệt vời, cảm ơn! –

+0

Có một ví dụ khi trả về bằng tham chiếu rvalue có hữu ích không? Dường như không? :( –

Các vấn đề liên quan