Câu hỏi Các tham chiếu * non * -const có kéo dài tuổi thọ của các thời gian không?


Ngày xửa ngày xưa, tôi cho rằng mã như thế này sẽ thất bại:

const MyClass& obj = MyClass();
obj.DoSomething();

bởi vì đối tượng MyClass sẽ bị phá hủy khi kết thúc biểu thức đầy đủ của nó, hãy để obj như một tham chiếu lơ lửng. Tuy nhiên, tôi đã học được (ở đây) rằng điều này không đúng; tiêu chuẩn thực sự có một điều khoản đặc biệt cho phép tham chiếu const để giữ thời gian tồn tại cho đến khi các tham chiếu được tự hủy. Nhưng, nó đã được nhấn mạnh, chỉ const tài liệu tham khảo có sức mạnh này. Hôm nay tôi chạy mã dưới đây trong VS2012 như một thử nghiệm.

struct Foo
{
    Foo() { std::cout << "ctor" << std::endl; }
    ~Foo() { std::cout << "dtor" << std::endl; }
};

void f()
{
    Foo& f = Foo();
    std::cout << "Hello world" << std::endl;
}

Đầu ra khi gọi f() là:

ctor  
Hello world  
dtor  

Vì vậy, tôi đã xem xét tiêu chuẩn dự thảo C ++ 11, và chỉ tìm thấy điều này (§ 12.2 / 4):

Có hai ngữ cảnh trong đó các trạng thái tạm thời bị phá hủy tại một   điểm khác với kết thúc của biểu thức đầy đủ. Ngữ cảnh đầu tiên [không   ứng dụng]. Ngữ cảnh thứ hai là khi một tham chiếu bị ràng buộc với   tạm thời. Tạm thời mà tham chiếu bị ràng buộc hoặc   tạm thời là đối tượng hoàn chỉnh của một subobject mà   tham chiếu bị ràng buộc vẫn tồn tại trong suốt thời gian tham chiếu.

Từ const vắng mặt rõ ràng ở trên. Vì thế; có hành vi này đã được thay đổi cho C ++ 11, là tôi sai về const điều bắt đầu với, hoặc VS2012 có một lỗi và tôi chỉ không tìm thấy một phần có liên quan của tiêu chuẩn?


14
2018-05-15 17:57


gốc




Các câu trả lời:


Hành vi không thay đổi, bạn chỉ cần bật cấp cảnh báo của mình lên đến /W4. VisualStudio thực thi quy tắc mở rộng suốt đời ngay cả khi khôngconst Tham chiếu lvalue như một phần mở rộng của trình biên dịch. Trong bối cảnh này, ràng buộc một rvalue để khôngconst tham chiếu hoạt động giống như khi bạn đã gắn kết nó với const tài liệu tham khảo.

Với /W4 bạn sẽ thấy điều này:

warning C4239: nonstandard extension used : 'initializing' : conversion from 'Foo' to 'Foo &'
1>  A non-const reference may only be bound to an lvalue

Văn bản không cho phép ràng buộc giá trị bằng một giá trị khôngconst Tham khảo lvalue có thể được tìm thấy trong §8.5.3 / 5

- Nếu không, tham chiếu phải là tham chiếu lvalue đối với không bay hơi const loại (tức là, cv1 sẽ    const), hoặc tham chiếu sẽ là tham chiếu rvalue.
[ Thí 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

—Về ví dụ]

Phần thứ hai của câu lệnh được trích dẫn là điều cho phép ràng buộc tạm thời với một tham chiếu rvalue, như được hiển thị trong câu trả lời của litb.

string &&s = string("hello");

Điều này, kết hợp với quy tắc tiện ích mở rộng lâu dài trong §12.2 / 5, nghĩa là toàn bộ thời gian tạm thời sẽ khớp với thời gian tồn tại của tham chiếu (rvalue) mà nó liên kết.


13
2018-05-15 18:03



Thực tế là bạn được phép liên kết một giá trị rvalue với tham chiếu không phải là const lvalue chính nó là một phần mở rộng. - Brian
@ Brian Không phải là những gì tôi nói sao? - Praetorian
@Praetorian Thật vậy tôi làm. Vì vậy, quy tắc "chỉ tham chiếu const kéo dài tuổi thọ" là một tác dụng phụ của một số quy tắc khác cho biết rằng chỉ có tham chiếu const có thể được ràng buộc với giá trị? - dlf
@dlf Cuối cùng tìm thấy văn bản bạn đang tìm kiếm, xem câu trả lời cập nhật - Praetorian
@ dlf Chưa bao giờ có một quy tắc "chỉ tham chiếu const kéo dài tuổi thọ". Lâu trước khi quy tắc cấm khởi tạo tham chiếu không const với tạm thời, phần mở rộng của vòng đời được áp dụng cho tất cả các tham chiếu. - James Kanze


Từ const không bao giờ có mặt trong phần này. Quy tắc luôn luôn là (từ khi nào tôi có thể nhớ) một tạm thời được sử dụng để khởi tạo một tham chiếu có tuổi thọ của nó được mở rộng để khớp với tham chiếu, bất kể loại của tham chiếu.

Đôi khi vào cuối những năm 1980 (rất chuẩn), C ++ đã được giới thiệu quy tắc tạm thời không thể sử dụng để khởi tạo một tham chiếu không const. Khởi tạo tham chiếu không const với tạm thời sẽ vẫn kéo dài tuổi thọ (có lẽ), nhưng vì bạn không thể làm được ... Hầu hết các trình biên dịch được triển khai một giai đoạn chuyển đổi, trong đó một khởi tạo như vậy sẽ chỉ phát ra một cảnh báo (và tuổi thọ được mở rộng).

Vì một số lý do, khi Microsoft cuối cùng quyết định triển khai C ++ (một số thời gian vào đầu những năm 1990), họ quyết định không triển khai quy tắc mới và cho phép khởi tạo một tham chiếu không const với một tạm thời (thậm chí không có cảnh báo, tại một thời điểm khi hầu hết các nhà cung cấp khác dần dần chuyển cảnh báo lỗi). Và tất nhiên, việc triển khai quy tắc suốt đời thông thường.

Cuối cùng, trong C ++ 11, các kiểu tham chiếu mới đã được giới thiệu, cho phép khởi tạo (hoặc thậm chí bắt buộc) với tạm thời. Quy tắc về tuổi thọ của các thời gian không thay đổi, mặc dù; một tạm thời được sử dụng để khởi tạo một tham chiếu (bất kể loại tham chiếu) có kéo dài suốt đời.

(Với một vài ngoại lệ: tôi sẽ không khuyên bạn sử dụng tạm thời để khởi tạo tham chiếu thành viên lớp trong quá trình khởi tạo danh sách.)


11
2018-05-15 18:43



Bạn có thể giải thích về đoạn cuối cùng liên quan đến tài liệu tham khảo thành viên không? Nó không bao giờ xảy ra với tôi để làm điều này, dù sao, nhưng tôi muốn được quan tâm đến lý luận chính xác của bạn. - Christian Hackl
@ChristianHackl Thời gian sử dụng tạm thời để khởi tạo tham chiếu thành viên là không phải kéo dài đến tuổi thọ của tham chiếu; tuổi thọ của nó kết thúc ở cuối của hàm tạo (kết quả là một tham chiếu lơ lửng). - James Kanze
Cảm ơn bạn đã làm rõ. Tôi đã đoán như vậy một cách trực giác, nhưng thật tuyệt khi được xác nhận. Vẫn còn làm cho tôi tự hỏi tại sao một điều như vậy không yêu cầu một trình biên dịch chẩn đoán ở nơi đầu tiên. - Christian Hackl


Không, bởi vì tham chiếu rvalue không cần phải const, vì vậy báo giá chuẩn là chính xác

string &&s = string("hello");

Tuổi thọ vẫn được mở rộng. Các ràng buộc làm cho mã không hợp lệ đối với tham chiếu không phải l constue là tại khoản 8 (lưu ý rằng nó không phải là nơi thích hợp để chỉ thêm "const" và "tham chiếu rvalue" vv trong đoạn bạn trích dẫn. từ chối hoạt động của các ràng buộc như vậy, không chỉ nói rằng tuổi thọ của các ràng buộc như vậy không được mở rộng bởi vì bạn sẽ rời khỏi bản thân ràng buộc vẫn được cải thiện).


4
2018-05-15 18:10



Câu hỏi thực sự hỏi số ba có - không có câu hỏi nào xích lại với nhau. Không rõ tôi là người bạn đang trả lời Không đến. Hay bạn đang đưa ra câu trả lời tương tự cho cả ba? - Rob Kennedy