2013-05-11 31 views
6

Tôi biết trong C++ 03, một tham chiếu không phải const không thể bị ràng buộc với giá trị.Có hợp lệ để ràng buộc các tham chiếu không liên quan đến giá trị trong C++ 11? (Sửa đổi)

T& t = getT(); không hợp lệ và trong C++ 11, chúng tôi có thể thực hiện việc này: T&& t = getT(); nhưng mã trên sẽ có tác dụng gì trong C++ 11?

Tôi đã thử nghiệm mã dưới đây với vs11:

Foo getFoo() { 
    return Foo(); 
} 

void fz(Foo& f) { 
} 

int getInt() { 
    return int(); 
} 

void iz(int& i) { 
} 

int main() { 
    { 
    Foo& z = getFoo(); //ok 
    fz(getFoo()); //ok 

    int& z2 = getInt(); //error: initial value of reference to non-const must be an lvalue 
    iz(getInt()); //same as above 
    } 
} 

Foo là một lớp tùy chỉnh, tôi không hiểu tại sao hai dòng đầu tiên compiles.The tạm thời được tham chiếu bởi z được destructed ở phần cuối của khu vực nội phạm vi chính. Liệu tiêu chuẩn có nói gì về điều này?

class Foo { 
public: 
    Foo() { 
    std::cout << "constructed\n"; 
    } 
    ~Foo() { 
    std::cout << "destructed\n"; 
    } 
}; 

Tôi chỉ thấy một câu hỏi tương tự: One VS2010 bug ? Allowing binding non-const reference to rvalue WITHOUT EVEN a warning?

+4

Thật thú vị như thế nào * vài lập trình viên * Objective-C hoặc Java đặt câu hỏi về esoterica ngôn ngữ theo định hướng như "Có phải nó có giá trị ràng buộc rvalues với các tham chiếu không liên quan đến const-const ...? " Hoặc phải tự quan tâm đến những thứ như "tài liệu tham khảo tạm thời ... bị hủy ở cuối phạm vi bên trong". Chỉ cần sayin ';) – paulsm4

+0

Bạn có thể đăng cách bạn đã xác định Foo hay không. – Gisway

+0

quy tắc ràng buộc không thay đổi tham chiếu Lvalue wrt AFAIK –

Trả lời

5

có nên hoạt động trong C++ 11 không?

Không, không được.

Foo là một lớp tùy chỉnh, tôi không hiểu tại sao hai dòng đầu tiên biên dịch

Nó biên dịch chỉ với MSVC. MSVC có phần mở rộng trình biên dịch (có thể cho là hữu ích) cho phép các giá trị ràng buộc của các loại do người dùng xác định đối với các giá trị, nhưng bản thân tiêu chuẩn sẽ cấm điều này. Xem, ví dụ: this live example nơi GCC 4.7.2 từ chối biên dịch mã của bạn.

Tiêu chuẩn có nói gì về điều này không?

Thực tế là vậy. Mỗi đoạn 8.5.3/5 của C++ 11 Tiêu chuẩn:

Một tham chiếu đến gõ “cv1 T1” được khởi tạo bởi một biểu hiện của loại “cv2 T2” như sau:

- Nếu tham chiếu là một tài liệu tham khảo giá trị trái và biểu thức khởi tạo

- là một giá trị trái (nhưng không phải là một chút-field), và “cv1 T1” là tài liệu tham khảo tương thích với “cv2 T2,” hoặc

- có loại lớp (ví dụ: T2 là loại lớp), trong đó T1 không liên quan đến tham chiếu đến T2 và có thể là chuyển đổi hoàn toàn thành loại giá trị "cv3 T3", "cv1 T1" tương thích với tham chiếu “cv3 T3” [...],

sau đó tham chiếu là ràng buộc để vế trái biểu initializer trong trường hợp đầu tiên và kết quả giá trị trái của việc chuyển đổi trong trường hợp thứ hai (hoặc, trong cả hai trường hợp, để lớp con cơ sở thích hợp của đối tượng). [...]

[...]

- Nếu không, các tài liệu tham khảo sẽ là một tài liệu tham khảo giá trị trái để một kiểu const non-volatile (ví dụ, CV1 sẽ const), hoặc các tài liệu tham khảo có trách nhiệm là một tham chiếu rvalue. [Ví dụ:

double& rd2 = 2.0; // error: not an lvalue and reference not const 
int i = 2; 
double& rd3 = i; // error: type mismatch and reference not const 

-end dụ]

0

Không bạn không thể ràng buộc một tạm thời đến một tài liệu tham khảo giá trị trái không const.

T f(); 

T& t1 = f(); // won't compile 
const T& t2 = f(); // OK 
T&& t3 = f(); // OK 

Đây là tính năng an toàn. Việc đột biến tạm thời bởi một giá trị sắp sửa chết thì rất có thể là lỗi logic, do đó ngôn ngữ không được phép.

Lưu ý rằng do sự RVO hơn trong thực tế:

T&& t3 = f(); 

T t3 = f(); 

là equivilent.

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