2010-06-12 39 views
10

Trong C++ 11, các phương thức có thể bị quá tải khi biểu thức có biểu thị đối tượng mà phương thức được gọi là một giá trị hoặc một giá trị. Nếu tôi trở *this từ một phương pháp gọi là thông qua một rvalue, tôi cần phải rõ ràng move từ *this hay không?Di chuyển từ * phương thức này bằng phương pháp rvalue?

Foo Foo::method() && 
{ 
    return std::move(*this); // Is this move required or not? 
} 

Thật không may, tôi không thể chỉ đơn giản là kiểm tra điều này trên trình biên dịch của tôi từ khi g ++ không hỗ trợ tính năng này chưa :(

+0

tôi mong đợi 'cái move' được yêu cầu, là 'this' là một rvalue tên, tương tự như nếu một hàm nhận một tham số rvalue. Nhưng không làm cho nó một câu trả lời kể từ khi tôi không thể trích dẫn chương và câu trên nó :) – jalf

+0

@ jalf: Và tôi mong đợi di chuyển được yêu cầu từ thường '* E' là một lvalue, nhưng ai biết :) Và tôi có chưa bao giờ nghe nói về giá trị rvalues ​​trước đây. Bạn có chắc về điều này"? (không có ý định chơi chữ!) – fredoverflow

+0

Giá trị được đặt tên là một thuật ngữ mới được giới thiệu để phân biệt các cuộc gọi quá tải có liên quan đến tham chiếu. ví dụ. nếu chúng ta có 'foo (X & x)' và 'foo (X && x)', hàm 'foo (someX)' là gì, nghĩa là 'someX' là' X & 'hay' X && '? Câu trả lời là 'X &' bởi vì 'someX' có một tên - nó là một rvalue có tên, là một' X & '. Nếu chúng ta gọi 'foo (someX + something) 'thì nó sẽ là một' X && 'bởi vì các biểu thức không có" tên ". –

Trả lời

4

Loại *thisluôn một giá trị trái:

§9.3.2 [class.this] p1

Trong phần nội dung của hàm thành viên không phải là tĩnh (9.3), từ khóa this là biểu thức giá trị có giá trị là địa chỉ của đối tượng mà hàm được gọi. Các loại this trong một hàm thành viên của một lớp X. [...]

§5.3.1 [expr.unary.op] p1

Các unary * điều hành thực hiện gián tiếp: biểu thức mà nó được áp dụng sẽ là một con trỏ đến một loại đối tượng, hoặc một con trỏ đến một loại chức năng và kết quả là một lvalue đề cập đến đối tượng hoặc chức năng mà biểu thức trỏ tới.

Vì vậy, bạn cần phải std::move nếu bạn muốn gọi hàm khởi tạo.

Đoạn mã sau đây cho thấy rằng:

#include <iostream> 
#include <utility> 

struct test{ 
    test(){} 
    test(test const&){ std::cout << "copy ctor // #1\n"; } 
    test(test&&){ std::cout << "move ctor // #2\n"; } 

    test f_no_move() &&{ return *this; } 
    test f_move() &&{ return std::move(*this); } 
}; 

int main(){ 
    test().f_no_move(); // #1 
    test().f_move(); // #2 
} 

Sử dụng Clang 3.1 (trình biên dịch duy nhất tôi biết mà thực hiện ref-vòng loại), tôi nhận được kết quả như sau:

$ kêu vang ++ -std = C++ 0x -stdlib = libC++ -pedantic Wall t.cpp
$ ./a.out
sao chép ctor // # 1
di chuyển ctor // # 2

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