2009-07-17 42 views
8

Mã nên giải thích điều:C++: con trỏ thành viên được khởi tạo? mẫu

class A 
{ 
    B* pB; 
    C* pC; 
    D d; 

    public : 
    A(int i, int j) : d(j) 
    { 
     pC = new C(i, "abc"); 
    } // note pB is not initialised, e.g. pB(NULL) 

    ... 
}; 

Rõ ràng PB nên được khởi tạo để NULL rõ ràng để được an toàn (và rõ ràng), nhưng, như nó đứng, giá trị của PB sau khi xây dựng của A là gì? Nó có được khởi tạo mặc định (không bằng 0) hay không (nghĩa là không xác định và bất kỳ thứ gì trong bộ nhớ). Tôi nhận ra initialisation trong C++ có một vài quy tắc công bằng.

Tôi nghĩ nó không được khởi tạo mặc định; như chạy trong chế độ gỡ lỗi trong Visual Studio nó đã thiết lập pB trỏ đến 0xcdcdcdcd - có nghĩa là bộ nhớ đã được new'd (trên heap) nhưng không được khởi tạo. Tuy nhiên trong chế độ phát hành, pB luôn trỏ đến NULL. Đây chỉ là tình cờ, và do đó không được dựa vào; hoặc là những trình biên dịch khởi tạo nó cho tôi (ngay cả khi nó không phải trong tiêu chuẩn)? Nó cũng có vẻ là NULL khi biên dịch với trình biên dịch của Sun trên Solaris.

Tôi thực sự đang tìm kiếm một tham chiếu cụ thể cho tiêu chuẩn để nói theo cách này hay cách khác.

Cảm ơn.

+4

Không xác định (và một số trình biên dịch sẽ cảnh báo), nhưng tôi không có chuẩn C++ tiện dụng ... – ephemient

+4

B là một con trỏ ngẫu nhiên vào tự nhiên. Chú thích. Trong chế độ gỡ lỗi, hầu hết trình biên dịch sẽ khởi tạo nó thành NULL (được cho là để giúp gỡ lỗi). Nhưng trong chế độ phát hành nó sẽ có giá trị trước đó trong bộ nhớ. –

Trả lời

11

Dưới đây là những đoạn văn có liên quan fromt ông tiêu chuẩn:

12.6.2 Khởi tạo các căn cứ và các thành viên [class.base.init]

4 Nếu một thành viên dữ liệu không tĩnh nhất định hoặc lớp cơ sở không phải là được đặt tên bởi một mem-
initializer-id trong mem-initializer-list, sau đó

--Nếu như các thực thể là một dữ liệu không tĩnh thành viên của (có thể cv-đủ điều kiện) loại lớp (hoặc mảng của chúng) hoặc một lớp cơ sở, và lớp thực thể là một lớp không phải POD, thực thể được khởi tạo mặc định (dcl.init). Nếu thực thể là thành viên dữ liệu phi tuyến của loại có đủ điều kiện, thì lớp thực thể phải có hàm tạo mặc định do người dùng khai báo.

- Nếu không, pháp nhân không phải là được khởi tạo. Nếu pháp nhân là loại tham chiếu hoặc loại tham chiếu đủ điều kiện hoặc loại có thể (hoặc trực tiếp hoặc gián tiếp) chương trình là ill- được hình thành.

Sau khi cuộc gọi đến một nhà xây dựng cho lớp X đã hoàn thành, nếu một thành viên

của X không phải là dự định tại mem-initializers các constructor của, cũng không
mặc định khởi tạo, và cũng không khởi trong khi thì hành phần thân của
hàm tạo, thành viên có giá trị không xác định.

+2

vì vậy nó chưa được khởi tạo và có thể trỏ tới bất kỳ thứ gì. Nội dung này có thể được thực hiện bằng cách triển khai, tức là fdfdfdfd cho thư viện debugheap. – xtofl

1

Tôi tin rằng đây là một tạo phẩm từ những ngày cũ C tốt khi bạn không thể có kỳ vọng về bộ nhớ phân bổ chứa. Khi các tiêu chuẩn tiến tới C++, "quy ước" này được duy trì. Khi các trình biên dịch C++ phát triển các tác giả cá nhân đã tự mình tự khắc phục vấn đề này. Do đó số dặm của bạn có thể khác nhau tùy thuộc vào trình biên dịch bạn chọn.

"0xcdcdcdcd" có vẻ là mẫu có thể nhận dạng dễ dàng "giúp" gỡ lỗi mã của bạn. Đó là lý do tại sao nó không hiển thị trong chế độ phát hành.

Tôi hy vọng điều này sẽ giúp ích một chút và chúc may mắn.

0

Con trỏ chưa được khởi tạo có thể trỏ đến bất kỳ thứ gì. Một số nhà cung cấp trình biên dịch sẽ giúp bạn ra ngoài và làm cho họ trỏ đến 0 hoặc 0xcdcdcdcd hoặc bất cứ điều gì.

Để đảm bảo mã của bạn an toàn và di động, bạn nên luôn khởi tạo con trỏ của mình. hoặc là 0 hoặc giá trị hợp lệ.

ví dụ:

C* pc = 0; 

hoặc

C* pc = new C(...); 

Nếu bạn luôn luôn khởi trỏ đến 0 thì đây là an toàn:

if (!pc) 
    pc = new C(...); 

Nếu bạn không khởi sau đó bạn đã có không có cách nào nói được khởi tạo và các con trỏ chưa được khởi tạo.

Như một sang một bên, không có từ khóa nào trong C++ là NULL. Hầu hết các trình biên dịch định nghĩa NULL là 0, nhưng nó không được coi là di động để sử dụng nó. Tiêu chuẩn C++ 0x mới sẽ giới thiệu một từ khóa mới, nullptr, vì vậy khi chúng xuất hiện, cuối cùng chúng ta sẽ có một hằng số con trỏ null.

0

Giá trị của pB không xác định. Nó có thể hoặc có thể không nhất quán với cùng một giá trị - thường phụ thuộc vào những gì trước đây ở cùng một vị trí trong bộ nhớ trước khi phân bổ một trường hợp cụ thể của A.

0

Con trỏ chưa được khởi tạo cho phép về cơ bản chứa giá trị ngẫu nhiên, mặc dù một số trình biên dịch có xu hướng điền chúng bằng 0 hoặc một số giá trị có thể nhận biết khác, đặc biệt là ở chế độ gỡ lỗi.

IMHO điều này là do thiết kế "không trả tiền cho những gì bạn không sử dụng" của C++. Nếu bạn không xem xét nó quan trọng, trình biên dịch không cần phải trải qua chi phí khởi tạo biến cho bạn. Tất nhiên, một khi bạn đã đuổi theo một con trỏ ngẫu nhiên, bạn có thể thấy nó thận trọng để khởi tạo nó trong thời gian tới ...

+0

Bạn không có nghĩa là, "* Không * trả tiền cho những gì bạn không sử dụng"? – Imagist

+0

Errr .... Có. Cảm ơn bạn đã chỉ ra điều đó. –

4

Theo phần C++0x standard 12.6.2.4, trong trường hợp biến con trỏ của bạn, nếu bạn không không bao gồm nó trong danh sách khởi tạo và bạn không đặt nó trong phần thân của hàm tạo, sau đó nó có giá trị không xác định. 0xCDCDCDCD và 0 là hai giá trị như vậy, cũng như bất kỳ giá trị nào khác. :-)

0

Rất hiếm khi tôi khuyên bạn không nên học điều gì đó về ngôn ngữ bạn đang sử dụng, nhưng trong trường hợp này, có hay không pB được khởi tạo không phải là thông tin hữu ích. Chỉ cần khởi tạo nó. Nếu nó được tự động khởi tạo, trình biên dịch sẽ tối ưu hóa việc khởi tạo thêm. Nếu không, bạn đã thêm một hướng dẫn xử lý bổ sung và ngăn chặn toàn bộ các lỗi tiềm ẩn.

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