Câu trả lời:
An toàn rồi. Const ref kéo dài thời gian sống tạm thời. Phạm vi sẽ là phạm vi của const ref.
Thời gian tồn tại của một đối tượng tạm thời có thể được kéo dài bằng cách liên kết với tham chiếu const lvalue hoặc tham chiếu giá trị (kể từ C ++ 11), xem chi tiết khởi tạo tham chiếu .
Bất cứ khi nào một tham chiếu bị ràng buộc với tạm thời hoặc một tiểu dự án, thời gian tạm thời được kéo dài để phù hợp với thời gian của tham chiếu, với các ngoại lệ sau :
- một ràng buộc tạm thời với giá trị trả về của hàm trong câu lệnh return không được mở rộng: nó bị hủy ngay lập tức ở cuối biểu thức trả về. Hàm như vậy luôn trả về một tham chiếu lơ lửng.
- một ràng buộc tạm thời với một thành viên tham chiếu trong danh sách trình khởi tạo hàm tạo chỉ tồn tại cho đến khi hàm tạo thoát ra, không chừng nào đối tượng tồn tại. (lưu ý: việc khởi tạo như vậy không được định hình kể từ DR 1696).
- tạm thời bị ràng buộc với một tham số tham chiếu trong lệnh gọi hàm tồn tại cho đến khi kết thúc biểu thức đầy đủ chứa lệnh gọi hàm đó: nếu hàm trả về một tham chiếu, tồn tại lâu hơn biểu thức đầy đủ, nó trở thành tham chiếu lơ lửng.
- một ràng buộc tạm thời với một tham chiếu trong trình khởi tạo được sử dụng trong biểu thức mới tồn tại cho đến khi kết thúc toàn bộ biểu thức có chứa biểu thức mới đó, không dài bằng đối tượng được khởi tạo. Nếu đối tượng khởi tạo tồn tại lâu hơn biểu thức đầy đủ, thành viên tham chiếu của nó trở thành tham chiếu lơ lửng.
- tạm thời bị ràng buộc với một tham chiếu trong phần tử tham chiếu của tổng hợp được khởi tạo bằng cú pháp khởi tạo trực tiếp (dấu ngoặc đơn) trái với cú pháp khởi tạo danh sách (dấu ngoặc) tồn tại cho đến khi kết thúc biểu thức đầy đủ chứa trình khởi tạo.
struct A { int&& r; }; A a1{7}; // OK, lifetime is extended A a2(7); // well-formed, but dangling reference
Nói chung, thời gian tồn tại tạm thời không thể được kéo dài thêm bằng cách "truyền lại": tham chiếu thứ hai, được khởi tạo từ tham chiếu mà tạm thời bị ràng buộc, không ảnh hưởng đến tuổi thọ của nó.
như @Konrad Rudolph đã chỉ ra (và xem đoạn cuối ở trên):
"Nếu
c.GetSomeVariable()
trả về một tham chiếu đến một đối tượng cục bộ hoặc một tham chiếu mà chính nó đang kéo dài thời gian tồn tại của một số đối tượng, thì phần mở rộng trọn đời không hoạt động"
c.GetSomeVariable()
trả về một tài liệu tham khảo cho một đối tượng tại địa phương hoặc một tham chiếu rằng nó là chính nó kéo dài tuổi thọ của một số đối tượng, mở rộng đời nào không kick in.
Không nên có vấn đề ở đây, nhờ gia hạn trọn đời . Đối tượng mới được xây dựng sẽ tồn tại cho đến khi tham chiếu đi ra khỏi phạm vi.
Điều này là an toàn.
[class.temporary]/5
: Có ba bối cảnh trong đó 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 đủ . [..]
[class.temporary]/6
: Bối cảnh thứ ba là khi một tham chiếu được liên kết với một đối tượng tạm thời. Đối tượng tạm thời mà tham chiếu bị ràng buộc hoặc đối tượng tạm thời là đối tượng hoàn chỉnh của một tiểu dự án mà tham chiếu bị ràng buộc tồn tại trong suốt thời gian của tham chiếu nếu giá trị tham chiếu được tham chiếu thông qua một trong các điều sau đây : [rất nhiều thứ ở đây]
Nó là an toàn trong trường hợp cụ thể này. Tuy nhiên, xin lưu ý rằng không phải tất cả các thời gian đều an toàn để chụp bằng tham chiếu const ... ví dụ:
#include <stdio.h>
struct Foo {
int member;
Foo() : member(0) {
printf("Constructor\n");
}
~Foo() {
printf("Destructor\n");
}
const Foo& method() const {
return *this;
}
};
int main() {
{
const Foo& x = Foo{}; // safe
printf("here!\n");
}
{
const int& y = Foo{}.member; // safe too (special rule for this)
printf("here (2)!\n");
}
{
const Foo& z = Foo{}.method(); // NOT safe
printf("here (3)!\n");
}
return 0;
}
Tham chiếu thu được cho z
KHÔNG an toàn để sử dụng vì thể hiện tạm thời sẽ bị hủy ở cuối biểu thức đầy đủ, trước khi đến printf
câu lệnh. Đầu ra là:
Constructor
here!
Destructor
Constructor
here (2)!
Destructor
Constructor
Destructor
here (3)!