2012-01-08 41 views
5

Tại sao GCC 4.7 phàn nàn khi khởi tạo một lớp bên trong một hàm (với một con trỏ)?Cảnh báo GCC [Wuninitialized]

Xấu:

#include "foo.h" 

int fn() { 
    Foo *foo; 
    foo->method(); 

    return 0; 
} 

main.cpp: Trong chức năng thành viên 'int foo()': main.cpp: 21: 52: cảnh báo: 'fn' có thể được sử dụng chưa được khởi tạo trong này chức năng [-Wuninitialized]

Tốt:

#include "foo.h" 

Foo *foo; 

int fn() { 
    foo->method(); 

    return 0; 
} 

Tốt:

#include "foo.h" 

int fn() { 
    Foo foo; 
    foo.method(); 

    return 0; 
} 
+1

Biến tĩnh được khởi tạo giá trị, do đó đoạn mã thứ 2 không gây ra cảnh báo. Đối với phần còn lại, chọn một cuốn sách hay về C++. –

+0

Bạn có thể vui lòng cẩn thận để đăng lỗi chính xác như chúng được báo cáo bởi trình biên dịch cho mã chính xác mà bạn đã đăng. "main.cpp: Trong hàm thành viên 'int foo()': main.cpp: 21: 52: cảnh báo: 'fn' có thể được sử dụng uninitialized trong hàm này [-Wuninitialized]" Điều này không có ý nghĩa, 'foo' không phải là một hàm cho phép một mình một hàm thành viên và 'fn' không phải là một biến. –

+0

Có vẻ như tên 'foo' và' fn' đã được đảo ngược trong thông báo lỗi bạn đã sao chép. Các thông điệp trình biên dịch đó hoặc C++ đã đạt được một mức độ sai lệch mới. – user268396

Trả lời

6

Có sự khác biệt giữa Foo * foo;Foo foo; Đầu tiên khai báo một con trỏ đến một Foo, thứ hai tuyên bố & gọi mặc định-constructor của một Foo.

EDIT: Có thể bạn muốn viết Foo * foo= new Foo();, để phân bổ một Foo trên heap có thể sống lâu hơn cuộc gọi chức năng.

2

Foo* foo; foo->method()không bao giờ. foo là một con trỏ chưa được khởi tạo có khả năng trỏ tới rác và như vậy mã của bạn thể hiện hành vi không xác định. tốt nhất bạn có thể hy vọng là trình biên dịch cảnh báo hoặc phát hiện lỗi trên bạn. Nếu không có điều đó, thì ít nhất hy vọng rằng chương trình đang chạy bị treo.

2

Trong ví dụ xấu foo là biến cục bộ có loại con trỏ, không được tự động khởi tạo. class Foo, trong ví dụ chính xác của bạn, được khởi tạo bằng cách sử dụng hàm tạo mặc định.

Đầu tiên của bạn »tốt« ví dụ khởi tạo con trỏ với 0, bởi vì foo là một biến toàn cục. Nó sẽ dẫn đến hành vi không xác định khi chạy, vì foo không trỏ đến một đối tượng.

2

vì, giống như cảnh báo cho biết, nó chưa được khởi tạo. không có đối tượng nào. thực sự giá trị của foo trong ví dụ đầu tiên của bạn là không xác định. nó sẽ có giá trị nằm trong bộ nhớ mà foo sống.

để làm rõ, foo (mà bạn thấy là Foo *) thực ra là int. giá trị của int được coi là địa chỉ cho một đối tượng kiểu Foo. để làm cho nó như vậy, bạn phải gán cho nó địa chỉ của một foo. một để làm điều này là để nhanh chóng nó với mới:

Foo* foo = new Foo; 

new trả về địa chỉ nơi đối tượng Foo mới đã được tạo ra. điều này sẽ xóa cảnh báo của bạn :)

5

Cái đầu tiên (xấu), foo đang trỏ đến con trỏ rác. Bạn có thể loại bỏ các cảnh báo bằng cách khởi tạo nó như Foo* foo = NULL; nhưng sau đó bạn sẽ nhận được một lỗi khi bạn cố gắng dereference nó (lỗi thời gian chạy).

Người thứ hai (tốt) không phàn nàn vì C tự động khởi tạo biến trong phạm vi đơn vị dịch thành NULL hoặc 0 hoặc tương đương nếu chúng chưa được khởi tạo.

Người cuối cùng (tốt) không phàn nàn vì bạn đang gọi phương thức trên đối tượng và gán con trỏ hàm được trình biên dịch thực hiện, tương tự nhưng không giống như số 2. Vậy trình biên dịch đã biết địa chỉ của phương thức method và đã gán địa chỉ đó cho vị trí thích hợp trên cấu trúc Foo.

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