2012-02-04 23 views
20

gì là sai với mã này, tại sao tôi nhận được câu trả lời sai:C++ constructor: rác trong khi khởi tạo các tham chiếu const

class X 
{ 
private: 
     const int a; 
     const int& b; 
public: 
     X(): a(10) , b(20) 
     { 
     //  std::cout << "constructor : a " << a << std::endl; 
     //  std::cout << "constructor : b " << b << std::endl; 
     } 

     void display() 
     { 
      std::cout << "display():a:" << a << std::endl; 
      std::cout << "display():b:" << b << std::endl; 

     } 
}; 


int 
main(void) 
{ 
     X x; 
     x.display(); 
return 0; 
} 

Đoạn mã trên sẽ cho tôi kết quả như

display():a:10 
display():b:1104441332 

Nhưng Nếu tôi xóa 2 dòng nhận xét bên trong hàm tạo mặc định, nó sẽ cho tôi kết quả phù hợp là

constructor : a 10 
constructor : b 20 
display():a:10 
display():b:20 

vui lòng trợ giúp, Cảm ơn bạn

Trả lời

24

Bạn đang khởi tạo b làm tham chiếu đến tạm thời.

Giá trị 20 được tạo và chỉ tồn tại cho phạm vi của hàm tạo.

Hành vi của mã sau đây rất thú vị - trên máy tính của tôi, tôi nhận được các giá trị khác với những cái bạn đã đăng, nhưng hành vi cơ bản vẫn không xác định.

Điều này là do khi giá trị mà các điểm tham chiếu nằm ngoài phạm vi, nó bắt đầu tham chiếu đến bộ nhớ rác thay thế, cho hành vi không thể đoán trước.

Xem Does a const reference prolong the life of a temporary?; câu trả lời https://stackoverflow.com/a/2784304/383402 liên kết đến các phần có liên quan của C++ chuẩn, đặc biệt là văn bản dưới đây:

A temporary bound to a reference member in a constructor’s ctor-initializer 
(12.6.2) persists until the constructor exits. 

Đây là lý do tại sao bạn luôn có được giá trị ngay trong in ấn trong các nhà xây dựng, và hiếm khi sau (nhưng có thể đôi khi!) . Khi các nhà xây dựng thoát ra, các mối nguy hiểm tham chiếu và tất cả các cược được tắt.

+0

cảm ơn câu trả lời của bạn. giải thích kết quả. nhưng tôi có thể biết cách khởi tạo b? –

+1

@VivekBasappa: có tham chiếu đến một số biến, như bạn dự định. Hoặc, chỉ làm cho nó có giá trị như 'a'. –

+1

@VivekBasappa Đó là một 'int', vì vậy bạn có thể không muốn nó là một tài liệu tham khảo dù sao đi nữa. 'snot như sao chép một 'int' là tốn kém. – Borealid

4

b đề cập đến tạm thời. Những gì bạn đã đọc (khi in) là một vị trí không hợp lệ vào thời điểm nó được đọc vì tạm thời 20 về mặt kỹ thuật đã hết phạm vi.

Để giải thích kết quả không phù hợp:

Đó là hành vi không xác định. Những gì bạn thấy có thể khác nếu bạn:

  • thay đổi trình biên dịch của bạn
  • thay đổi các thiết lập trình biên dịch của bạn
  • xây dựng cho kiến ​​trúc khác
  • thay đổi lớp học của bạn bố trí thành viên
  • thêm hoặc loại bỏ những thứ từ vùng nhớ gần trường hợp của x
  • vv

Bạn nên luôn tránh hành vi không xác định.

Nhưng tại sao giá trị thay đổi? Tham chiếu của bạn có thể đề cập đến địa chỉ ngăn xếp đã được viết lại (ví dụ: được sử dụng lại) vào thời điểm được in.

+0

Tôi thành thật không thể hiểu được phần cuối cùng "về lý do tại sao nó khác ...". Tôi đánh giá cao nếu bạn có thể chỉ ra chính xác những gì bạn đang nói về. Ngay cả lần đầu tiên "như cho tại sao:" không phải là tất cả những gì rõ ràng, mặc dù những gì sau sau khi ':' không có ý nghĩa. – batbrat

+0

@batbrat được mở rộng – justin

+1

+1 Làm tốt lắm! Bây giờ nó có ý nghĩa tốt hơn nhiều. – batbrat

3

Bạn đang ràng buộc const& thành tạm thời, không tồn tại ngoài cuộc gọi tới hàm tạo. Tiêu chuẩn C++ 03 nói một cách cụ thể "một ràng buộc tạm thời 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" (12.2/5 "đối tượng tạm thời").

Vì vậy, mã của bạn có hành vi không xác định - bạn có thể nhận được vô nghĩa, hoặc một cái gì đó mà dường như là 'làm việc'.

FWIW, MSVC 2010 cung cấp cho các cảnh báo sau đây trên mã rằng:

C:\temp\test.cpp(12) : warning C4413: 'X::b' : reference member is initialized to a temporary that doesn't persist after the constructor exits 
19

tôi sẽ cho câu trả lời của tôi biên dịch này một:

$ g++ -std=c++98 -Wall -Wextra -pedantic test.cpp 
test.cpp: In constructor 'X::X()': 
test.cpp:9:26: warning: a temporary bound to 'X::b' only persists until the constructor exits [-Wextra] 
$ 

Bạn nên bật những lời cảnh báo về trình biên dịch của bạn như tốt.

+0

Cảm ơn câu trả lời, bạn có thể giải thích tại sao b là khởi tạo tạm thời không? Tôi đang cố gắng để khởi tạo giá trị const thông qua danh sách khởi tạo –

+1

@VivekBasappa: 'X :: b' là tham chiếu const, không phải là giá trị const. –

+1

@VivekBasappa 'const' không phải là vấn đề, vấn đề là nó là một * tham chiếu * mà không có gì để tham khảo. –

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