2015-10-27 15 views
6

Từ [12,8] [11] của N3337:Mặc định di chuyển constructor và tham khảo các thành viên

Các ngầm định nghĩa sao chép/di chuyển constructor cho một lớp X phi công đoàn thực hiện một sao chép ngầm/di chuyển các căn cứ của nó và các thành viên. [Lưu ý: brace-hoặc-bằng-initializers của các thành viên dữ liệu không tĩnh được bỏ qua. Xem thêm ví dụ trong 12.6.2. —end note] Thứ tự khởi tạo giống như thứ tự khởi tạo các căn cứ và các thành viên trong một hàm tạo do người dùng định nghĩa (xem 12.6.2). Gọi x là tham số của hàm tạo hoặc, đối với hàm tạo di chuyển, một xvalue tham chiếu đến tham số. Mỗi thành phần dữ liệu cơ bản hoặc không tĩnh được sao chép/di chuyển theo cách thích hợp với loại của nó:

- nếu thành viên là một mảng, mỗi phần tử được khởi tạo trực tiếp với phần con tương ứng của x;

- nếu thành viên m có loại tham chiếu rvalue T & &, nó được khởi tạo trực tiếp với static_cast<T&&>(x.m);

- nếu không, cơ sở hoặc thành viên được khởi tạo trực tiếp với cơ sở hoặc thành viên tương ứng của x.

Điều này thực sự rõ ràng hơn, nhưng tôi không thể thấy bất kỳ đề cập nào về các thành viên tham chiếu lvalue trong mệnh đề đó. Vì nó không đề cập đến chúng, theo mặc định nó có vẻ như nói rằng chúng là một phần của chuyển động thành viên ngầm, nhưng những điều sau đây sẽ không hoạt động;

int x = 5; 
int& y = x; 
int& z(std::move(y)); //error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'std::remove_reference<int&>::type {aka int}' 

Vậy là nó an toàn để giả định rằng các nhà xây dựng di chuyển mặc định phân biệt rằng một thành viên là một tài liệu tham khảo và sẽ chỉ đơn giản là chỉ làm

int& z = y; 

không có cuộc gọi đến std::move?

+0

Tham chiếu giá trị không được ràng buộc với xvalue, vì vậy 'int & z (std :: move (y));' không hợp lệ. 'int &z = y;' là hợp pháp và làm cho 'z' một tên thứ ba cho đối tượng' int' hiện đang được đặt tên là 'x' và' y'. Tôi không chắc câu hỏi của bạn là gì? –

+0

"trực tiếp khởi tạo" có nghĩa là đối với một thành viên 'm', nó được khởi tạo như thể bằng' T m (khác.m); ' –

+0

Tôi nghĩ rằng điều này liên quan đến (và có thể được giải quyết) http: // stackoverflow.com/questions/33344259/does-rvo-work-on-object-members – Sheljohn

Trả lời

6

Nó được xử lý bởi đặc tả của biểu thức truy cập thành viên lớp học. Phần quan trọng là

Hãy để tham số x là tham số của hàm tạo hoặc, đối với hàm tạo di chuyển, tham số x tham chiếu đến tham số.

Nói cách khác, một động thái constructor defaulted cho

struct X { int x, &y; }; 

không tương đương với

X::X(X&& other) : x(std::move(other).x), y(std::move(other).y) {} 

Điều quan trọng ở đây là kết quả của một biểu thức truy cập thành viên lớp x.m, nơi m tên là thành viên dữ liệu không tĩnh, luôn là một giá trị nếu m có loại tham chiếu, nhưng xvalue nếu x là giá trị và m có loại không tham chiếu. (Xem [expr.ref]/4.) Điều này đảm bảo rằng các thành viên tham chiếu lvalue sẽ được khởi tạo với các giá trị.

+1

'y (std :: move (khác) .y)' giống với 'y (other.y)', đúng không? –

+0

@ M.M Phải, để nhập tham chiếu 'y'. –

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