2015-01-27 15 views
9

Tôi biết tiêu chuẩn có ngoại lệ về việc kéo dài tuổi thọ của thời gian mà về cơ bản nói ràng buộc một tham chiếu const trong một hàm tạo sẽ không kéo dài tuổi thọ, nhưng điều này cũng áp dụng cho các chữ? Ví dụ:Có thể một const int ref trong một constructor một cách an toàn liên kết với một chữ?

class C { 
    private: 
     const int& ref; 
    public: 
     C(const int& in) 
      : ref{in} 
     { } 
}; 

Nếu tôi có một hàm trả về một đối tượng kiểu này

C f() { 
    C c(2); 
    return c; 
} 

giá trị của c.ref sẽ được định nghĩa trong người gọi nếu tôi biết đó là ràng buộc để một chữ?

+1

Câu trả lời có lẽ phụ thuộc vào nếu trình biên dịch tạo ra một giá trị tĩnh toàn cầu cho đen và các điểm tại đó, hoặc nếu nó tạo ra một giá trị ngăn xếp để trỏ vào. Có thể đi một trong hai cách. –

+0

Tại sao không chỉ truyền int theo giá trị? Nó sẽ hiệu quả hơn. – cppguy

+0

@cppguy đây là một ví dụ rất nhỏ về vấn đề thực tế. –

Trả lời

6

Không. Bạn sẽ không thể sử dụng tham chiếu sau khi hàm tạo kết thúc thực thi.
Khi giá trị của loại không thuộc loại được ràng buộc với một số const -reference cùng loại đó, tạm thời luôn được giới thiệu. Do đó tham chiếu tham số của hàm tạo sẽ tham chiếu đến một tạm thời bị hủy khi tài liệu tham khảo nằm ngoài phạm vi. Sau khi điều đó xảy ra, tham chiếu thành viên đang lơ lửng và cố truy cập giá trị được lưu trữ đằng sau kết quả tham chiếu đó trong UB. [dcl.init.ref]/5:

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

  • Nếu tham chiếu là tham chiếu lvalue và biểu thức khởi tạo
    • là một giá trị (nhưng không phải là trường bit) và [..]
    • có một loại lớp (ví dụ: T2 là một loại lớp) [..]
  • 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 non-volatile const loại (ví dụ:, cv1 phải là const) hoặc tham chiếu sẽ là tham chiếu giá trị.

    • Nếu biểu thức khởi tạo

      • là một Xvalue (nhưng không phải là một chút-field), lớp prvalue, mảng prvalue hoặc chức năng vế trái và [..]
      • có một loại lớp [ ..]
    • Nếu không: (5.2.2.1)

      • Nếu T1 là một loại lớp [..]
      • Nếu T1 là một loại phi giai cấp, tạm thời kiểu “CV1T1” được tạo ra và sao chép-khởi (8,5) từ biểu thức khởi tạo. Tham chiếu sau đó được liên kết với tạm thời.

Và literals số nguyên là, gì ngạc nhiên, thực sự prvalues. [expr.prim.general]/1:

Chuỗi chữ là một giá trị; tất cả các chữ khác đều là giá trị.

Cuối cùng, trong trường hợp này là không rõ ràng, [class.temporary]/5:

Các tạm thời để mà tham chiếu được đóng thành quyển hoặc tạm thời đó là đối tượng hoàn toàn của một subobject mà tài liệu tham khảo là ràng buộc kéo dài tuổi thọ của các tài liệu tham khảo trừ:

  • một ràng buộc tạm thời cho một thành viên tham khảo trong ctor-initializer của một nhà xây dựng (12.6.2) vẫn tồn tại cho đến khi const ructor thoát.
+1

Cũng trong tiêu chuẩn: __A tạm thời ràng buộc với một thành viên tham chiếu trong bộ khởi tạo của hàm khởi tạo (§12.6.2) vẫn tồn tại cho đến khi hàm khởi tạo thoát khỏi – MatiasFG

+0

Tốt đẹp! Chỉ mới nhìn vào điều này gần đây, đó là lý do tại sao tôi đã tham khảo (chơi chữ) trong tầm tay. – MatiasFG

+0

@MatiasFG Vâng, nhưng tôi đã không thực sự biết nơi để tìm (tôi chỉ có kế hoạch để tìm kiếm). Cảm ơn! – Columbo

1

Câu trả lời ngắn: Đánh giá c.ref gần như chắc chắn sẽ là bất hợp pháp (gọi hành vi không xác định).

Long trả lời: Khi ràng buộc một tham chiếu đến một số nguyên theo nghĩa đen, những gì bạn đang thực sự làm như sau:

Các nguyên nghĩa đen dùng để chỉ những gì được gọi là "a value that is not associated with an object".

Để ràng buộc một tham chiếu đến nó, một đối tượng cần phải được tạo giữ cùng một giá trị. Lý do cho rằng đó là một tham chiếu (hoặc con trỏ) phải luôn luôn trỏ đến một đối tượng (mà lần lượt là không có gì nhiều hơn một chút bộ nhớ). Do đó, đối tượng tạm thời được tạo để giữ giá trị.

Các đối tượng tạm thời được đảm bảo kéo dài miễn là biểu thức chúng được tạo ra đang được đánh giá. Vì đối tượng của bạn tồn tại lâu hơn, đối tượng tạm thời giữ giá trị của bạn đang bị hủy sớm và tham chiếu có thể không được truy cập nữa.

Lưu ý rằng nếu bạn truy cập c.ref trong biểu thức đã tạo c, bạn thực sự sẽ ổn.

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