2011-12-22 8 views
17

Đương nhiên, điều này sẽ không biên dịch:Các số có thể thay đổi được hay không?

int &z = 3; // error: invalid initialization of non-const reference .... 

và điều này sẽ biên dịch:

const int &z = 3; // OK 

Bây giờ, hãy xem xét:

const int y = 3; 
int && yrr = y; // const error (as you would expect) 
int && yrr = move(y); // const error (as you would expect) 

Nhưng những dòng này tới làm biên dịch đối với tôi . Tôi nghĩ nó không nên.

int && w = 3; 
int && yrr = move(3); 
void bar(int && x) {x = 10;} 
bar(3); 

Hai dòng cuối cùng có cho phép sửa đổi 3 chữ cái không? Sự khác nhau giữa 3 và const int là gì? Và cuối cùng, có nguy hiểm nào với việc 'sửa đổi' các chữ?

(g ++ - 4.6 (GCC) 4.6.2 với -std=gnu++0x -Wall -Wextra)

+1

Để trả lời câu hỏi của riêng tôi: Trong 'di chuyển (3)' có thể 3 được sao chép trước tiên để tạo một tạm thời int sẽ bị hủy ở cuối câu lệnh. Đây có phải là lời giải thích? –

+0

Trong tuyên bố thứ hai của bạn: const &z = 3; bạn thiếu trình chỉ định loại. vì vậy nó không biên dịch. –

+0

Cảm ơn, @CJohnson, tôi thường sao chép và dán mã làm việc tại đây. Nhưng tôi đã bất cẩn với một lớp lót đó! –

Trả lời

13

Các rvalue tham chiếu đến đen 3:

int && w = 3; 

là thực sự ràng buộc với một tạm thời mà là kết quả của việc đánh giá sự biểu hiện 3. Nó không bị ràng buộc đối với một số Platon đen 3.

(tất cả các tiêu chuẩn sau đây tài liệu tham khảo là từ dự thảo tháng ba năm 2011, n3242)

3.10/1 "lvalues ​​và rvalues"

The value of a literal such as 12, 7.3e5, or true is also a prvalue

Sau đó 8.5. 3 "Tài liệu tham khảo" cho các quy tắc cho cách một tài liệu tham khảo là ràng buộc rơi thông qua đối với trường hợp cuối cùng, mà nói:

Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expression using the rules for a non-reference copy-initialization (8.5). The reference is then bound to the temporary.

và đưa ra như một ví dụ một cái gì đó rất gần với những gì trong bạn câu hỏi:

double&& rrd = 2; // rrd refers to temporary with value 2.0 
+0

Cảm ơn, nhưng nếu đó là sự thật, thì không nên làm việc này? 'move (3) = 6;' Thay vào đó tôi gặp lỗi "* error: sử dụng xvalue (tham chiếu rvalue) làm lvalue *". Đó là thời gian để tôi đọc về xvalues ​​và prvalues ​​và tất cả những gì một lần nữa :-) –

+3

Nhờ câu trả lời của bạn, tôi nghĩ rằng tôi có thể trả lời bình luận của tôi một vài giây trước đây. Tôi có thể thấy rằng 'di chuyển (3) 'là một giá trị (rõ ràng, nó không có tên). Trong khi bên trong hàm của tôi 'void bar (int && x) {x = 10;}' có một tên cho 'x'. Điều này có vẻ là sự khác biệt giữa 'x = 6' và' di chuyển (3) = 6'. Cả hai đều là '&& 'nhưng một là một giá trị và cái kia là không. Và sự khác biệt này là điều dẫn đến thông báo lỗi cho 'di chuyển (3) = 6'. –

+0

@Aaron: (Một trễ) bổ sung cho nhận xét của bạn: Một nơi nào đó, tiêu chuẩn chỉ định rằng một rvalue được đặt tên là một giá trị, do đó, có, đó là chính xác cách hoạt động. :) – Xeo