2012-07-01 76 views
30

Trong một vài dự án mã cũ của tôi khi tôi chưa từng nghe đến con trỏ thông minh, bất cứ khi nào tôi cần kiểm tra xem con trỏ vẫn trỏ đến một đối tượng hợp lệ, tôi sẽ luôn làm một cái gì đó như thế này ...Nullptr và kiểm tra xem con trỏ trỏ đến một đối tượng hợp lệ

object * meh = new object; 
if(meh) 
    meh->member; 

Hoặc khi tôi cần thiết để xóa các đối tượng một cách an toàn, một cái gì đó giống như

if(meh) 
{ 
    delete meh; 
    meh = 0; 
} 

Vâng này, bây giờ tôi đã học về các vấn đề có thể phát sinh từ việc sử dụng các đối tượng và con trỏ trong các biểu thức boolean cả với các số theo nghĩa đen, theo cách cứng:. Và bây giờ tôi cũng đã học về tính năng không mới nhưng khá thú vị của C++, từ khóa nullptr. Nhưng bây giờ tôi tò mò.

Tôi đã trải qua và sửa đổi hầu hết mã của tôi do đó, ví dụ, khi xóa đối tượng tôi bây giờ viết

if(meh) 
{ 
    delete meh; 
    meh = nullptr; 
} 

Bây giờ tôi đang tự hỏi về boolean. Khi bạn chuyển, chỉ cần nói int vào câu lệnh if như thế này,

int meh; 
if(meh) 

Sau đó, nó kiểm tra hoàn toàn bằng 0 mà không cần viết.

if(meh == 0) // does the exact same check 

Bây giờ, C++ có làm tương tự cho con trỏ không? Nếu vượt qua trong một char * như thế này để một tuyên bố nếu?

char * meh; 
if(meh) 

Sau đó, nó sẽ hoàn toàn so sánh nó với nullptr? Vì tôi đã viết những ifs như thế này bao lâu, nên đây là bản chất thứ hai tại thời điểm này để kiểm tra xem con trỏ có hợp lệ trước khi sử dụng hay không bằng cách gõ if (object *) và sau đó gọi các thành viên của nó. Nếu đây không phải là chức năng thì tại sao lại không? Quá khó thực hiện? Sẽ giải quyết một số vấn đề bằng cách loại bỏ một cách nhỏ khác mà bạn có thể làm rối tung mã của bạn.

+22

Bạn không ** cần ** ckeck con trỏ trước khi 'xóa'. Nó là hoàn toàn an toàn để 'xóa' một' nullptr'. –

+1

Trong ví dụ cuối cùng của bạn, bạn có nghĩa là 'char * meh = nullptr; nếu (meh) '? Con trỏ không được khởi tạo. –

+3

Kết quả của biểu thức 'mới' của bạn sẽ không bao giờ là rỗng, ngoại lệ được sử dụng thay thế. An như đã đề cập, xóa null là tốt, nó không có gì. Ngoài ra, tốt hơn hết là không đặt lại giá trị con trỏ thành null. Lần cuối cùng nó được sử dụng nên là lần cuối cùng nó không phải là null, do đó, có quyền truy cập vào một con trỏ bị xóa nên được coi là một lỗi; thiết lập nó để ẩn nó. – GManNickG

Trả lời

32

Trong C, mọi thứ không phải là 0 đều đúng. Vì vậy, bạn chắc chắn có thể sử dụng:

if (ptrToObject) 
    ptrToObject->doSomething(); 

để trỏ con trỏ an toàn.

C++ 11 thay đổi trò chơi một chút, nullptr_t là một loại trong đó nullptr là một ví dụ; đại diện của nullptr_t là triển khai cụ thể. Vì vậy, một trình biên dịch có thể xác định nullptr_t tuy nhiên nó muốn. Nó chỉ cần chắc chắn rằng nó có thể áp dụng hạn chế thích hợp trên đúc của một nullptr_t với các loại khác nhau - trong đó boolean được phép - và chắc chắn rằng nó có thể phân biệt giữa một nullptr_t và 0.

Vì vậy nullptr sẽ đúng và đúc hoàn toàn vào booleanfalse miễn là trình biên dịch tuân theo đặc tả ngôn ngữ C++ 11. Và đoạn mã trên vẫn hoạt động.

Nếu bạn xóa đối tượng được tham chiếu, không có gì thay đổi.

delete ptrToObject; 
assert(ptrToObject); 
ptrToObject = nullptr; 
assert(!ptrToObject); 

Vì bao lâu tôi đã viết những IFS như thế này, nó là bản chất thứ hai vào thời điểm này để kiểm tra xem con trỏ hợp lệ trước khi sử dụng bằng cách gõ if (đối tượng *) và sau đó gọi các thành viên của nó.

số Hãy duy trì một biểu đồ thích hợp của các đối tượng (tốt nhất là sử dụng con trỏ độc đáo/thông minh). Như đã chỉ ra, không có cách nào để xác định xem một con trỏ không phải là nullptr trỏ đến một đối tượng hợp lệ hay không. Các onus là vào bạn để duy trì vòng đời anyway .. đây là lý do tại sao các trình bao bọc con trỏ tồn tại ở nơi đầu tiên.

+0

cũng yeh tôi biết điều đó. khi trái mà không cần so sánh, nếu các câu lệnh kiểm tra xem có bất cứ điều gì được truyền trong việc giải quyết bất cứ điều gì theo nghĩa đen hay không nhưng 0. nếu int meh = 0 thì nó giải quyết sai. Tuy nhiên, nếu địa chỉ của một int * là 0x000 vv có nghĩa là nó không trỏ vào bất cứ điều gì và bool sẽ giải quyết sai. nếu nó chỉ vào một nơi nào đó, thì nó không phải là số không và sau đó nó giải quyết sự thật. nhưng nếu bạn xóa đối tượng tại con trỏ thì sao? ptr stil chứa địa chỉ như 0x81A3 hoặc một cái gì đó, nhưng đối tượng đã biến mất. bạn gọi nếu, và nó giải quyết đúng, mặc dù không có một đối tượng ở đó. – FatalCatharsis

+1

sẽ gây ra lỗi thời gian chạy, nếu bạn quên không ra con trỏ. nhưng nếu con trỏ được so sánh hoàn toàn với nullptr, thì con trỏ là 0 hay đã giải quyết một cái gì đó, nó sẽ giải quyết sai khi đối tượng không có ở đó. – FatalCatharsis

+2

Có. Vậy câu hỏi của bạn là gì? – dcow

6

Không thể kiểm tra xem con trỏ trỏ đến một đối tượng hợp lệ hay không. Nếu con trỏ không phải là null nhưng không trỏ đến một đối tượng hợp lệ, sau đó sử dụng con trỏ gây ra hành vi không xác định. Để tránh loại lỗi này, onus là bạn phải cẩn thận với tuổi thọ của các đối tượng được chỉ định; và các lớp con trỏ thông minh trợ giúp với nhiệm vụ này.

Nếu meh là con trỏ thô thì không có sự khác biệt nào giữa if (meh)if (meh != 0)if (meh != nullptr). Tất cả đều tiến hành iff con trỏ không phải là null.

Có chuyển đổi tiềm ẩn từ chữ số 0 thành nullptr.

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