2009-04-01 34 views
108

Tôi luôn tự hỏi tại sao cài đặt tự động của con trỏ thành NULL sau khi xóa không phải là một phần của tiêu chuẩn. Nếu điều này được thực hiện chăm sóc sau đó nhiều tai nạn do một con trỏ không hợp lệ sẽ không xảy ra. Nhưng phải nói rằng tôi có thể nghĩ ra vài lý do tại sao tiêu chuẩn sẽ bị hạn chế này:Tại sao không xóa đặt con trỏ thành NULL?

  1. Hiệu suất:

    Một hướng dẫn bổ sung có thể làm chậm hiệu suất delete.

  2. Có thể do const con trỏ.

    Sau đó, một lần nữa tiêu chuẩn có thể đã làm điều gì đó cho trường hợp đặc biệt này tôi đoán.

Có ai biết lý do chính xác không cho phép điều này không?

Trả lời

138

Stroustrup himself câu trả lời. Một đoạn trích:

C++ cho phép một cách rõ ràng một thực hiện của xóa để không ra một toán hạng vế trái, và tôi đã hy vọng rằng việc triển khai sẽ làm điều đó, nhưng ý kiến ​​cho rằng dường như không có trở nên phổ biến với người thực hiện.

Nhưng vấn đề chính mà anh ấy đặt ra là đối số của xóa không cần phải là một giá trị.

12

Vì không thực sự cần thiết, và vì nó sẽ yêu cầu xóa việc lấy con trỏ đến con trỏ thay vì chỉ con trỏ.

+1

Hoặc tham chiếu đến con trỏ. –

+0

đúng, nhưng điều đó sẽ dẫn đến cùng một chi phí – snemarch

5

Nếu bạn có một chuỗi con trỏ, và hành động thứ hai của bạn là xóa mảng trống, thì không có thiết lập điểm cho mỗi giá trị rỗng khi bộ nhớ sắp được giải phóng. Nếu bạn muốn nó được null .. viết null cho nó :)

54

Đầu tiên, thiết lập để null sẽ yêu cầu một bộ nhớ được lưu biến. Đúng là bạn thường có một con trỏ trong một biến nhưng đôi khi bạn có thể muốn xóa một đối tượng ở một địa chỉ được tính toán. Điều đó sẽ là không thể với "vô hiệu hóa" xóa.

Sau đó, đến hiệu suất. Bạn có thể đã viết mã theo cách mà con trỏ sẽ ra khỏi phạm vi ngay lập tức sau khi xóa xóa. Điền nó với null chỉ là một sự lãng phí thời gian. Và C++ là một ngôn ngữ với "không cần nó? Sau đó bạn không phải trả tiền cho nó" ý thức hệ.

Nếu bạn cần sự an toàn, có nhiều loại con trỏ thông minh trong dịch vụ của bạn hoặc bạn có thể viết con trỏ của riêng mình - tốt hơn và thông minh hơn.

+4

Địa chỉ được tính toán điểm tốt, ngay cả khi đó là điều bạn không thấy thường xuyên – snemarch

+0

bạn đang nói về vị trí mới khi bạn nói rằng đôi khi bạn có thể muốn xóa một đối tượng địa chỉ tính toán. ??? – Destructor

+0

@PravasiMeet Không, ý tôi là một cái gì đó như 'delete (ptr + i)' – sharptooth

35

Bạn có thể có nhiều con trỏ trỏ tới bộ nhớ đó. Nó sẽ tạo ra một cảm giác an toàn giả nếu con trỏ bạn chỉ định cho xóa đã được đặt thành null, nhưng tất cả các con trỏ khác thì không. Một con trỏ không là gì hơn là một địa chỉ, một số. Nó cũng có thể là một int với một hoạt động dereference. Quan điểm của tôi là bạn cũng sẽ phải quét từng con trỏ đơn để tìm những người đang tham chiếu cùng một bộ nhớ mà bạn vừa xóa, và vô hiệu hóa chúng. Nó sẽ được tính toán dữ dội để quét tất cả các con trỏ cho địa chỉ đó và vô hiệu hóa chúng ra, bởi vì ngôn ngữ không được thiết kế cho điều đó. (Mặc dù một số ngôn ngữ khác cấu trúc tham chiếu của chúng để hoàn thành một mục tiêu tương tự theo cách khác.)

17

Một con trỏ có thể được lưu trong nhiều biến, thiết lập một trong số này thành NULL sẽ vẫn để lại con trỏ không hợp lệ trong các biến khác. Vì vậy, bạn không thực sự đạt được nhiều, bạn có nhiều khả năng tạo ra một cảm giác an toàn sai lầm.

Bên cạnh đó, bạn có thể tạo chức năng của riêng bạn mà làm những gì bạn muốn:

template<typename T> 
void deleten(T *&ptr) { 
    delete ptr; 
    ptr = NULL; 
} 
4

C++ cho phép bạn xác định điều hành của riêng bạn mới và xóa để ví dụ họ sẽ sử dụng cấp phát hồ bơi riêng của bạn. Nếu bạn làm điều này thì nó có thể sử dụng mới và xóa với những thứ không đúng địa chỉ nhưng nói các chỉ mục trong mảng hồ bơi của bạn. Trong bối cảnh này giá trị của NULL (0) có thể có ý nghĩa pháp lý (đề cập đến mục đầu tiên trong nhóm).
Vì vậy, việc xóa đặt NULL tự động cho đối số của nó không phải lúc nào cũng có ý nghĩa - đặt giá trị thành giá trị không hợp lệ. Giá trị không hợp lệ có thể không phải lúc nào cũng là NULL.

3

Đặt con trỏ thành NULL tự động sẽ không giải quyết được hầu hết các vấn đề với việc sử dụng con trỏ xấu. Tai nạn duy nhất nó sẽ tránh được là nếu bạn cố gắng xóa nó hai lần. Nếu bạn gọi một hàm thành viên trên một con trỏ như vậy thì sao? Nó sẽ vẫn sụp đổ (giả sử rằng nó truy cập vào các biến thành viên). C++ không hạn chế bạn gọi bất kỳ hàm nào trên con trỏ NULL, cũng không nên làm điều đó từ quan điểm thực hiện.

4

Triết học của C++ là "trả tiền cho nó chỉ khi bạn sử dụng nó". Tôi nghĩ rằng nó có thể trả lời câu hỏi của bạn.

Ngoài ra đôi khi bạn có thể có heap của riêng bạn sẽ khôi phục bộ nhớ đã xóa .. hoặc đôi khi con trỏ không thuộc sở hữu của bất kỳ biến nào. Hoặc con trỏ được lưu trữ trong vài biến - nó có thể không chỉ là một trong số chúng.
Như bạn có thể thấy nó có nhiều vấn đề và các vấn đề có thể xảy ra.

7

delete được sử dụng chủ yếu trong destructors, trong trường hợp thiết lập một thành viên để NULL là vô nghĩa. Một vài dòng sau, vào lúc đóng cửa }, thành viên không còn tồn tại nữa. Trong các toán tử gán, xóa thường được theo sau bởi một phép gán.

Ngoài ra, nó sẽ làm cho đoạn mã sau bất hợp pháp:

T* const foo = new T; 
delete foo; 
4

Dưới đây là một lý do khác; giả sử xóa không đặt đối số của nó thành NULL:

int *foo = new int; 
int *bar = foo; 
delete foo; 

Thanh có được đặt thành NULL không? Bạn có thể khái quát hóa điều này không?

-2

Tôi thấy mọi người đưa ra câu trả lời kỳ lạ cho câu hỏi này.

ptr = NULL; Làm thế nào một tuyên bố đơn giản có thể gây chậm trễ hiệu suất?

Một câu trả lời khác là nói rằng chúng tôi có thể có nhiều con trỏ trỏ đến cùng một vị trí bộ nhớ . Chắc chắn chúng ta có thể.Trong trường hợp này, thao tác xóa trên một con trỏ sẽ chỉ làm cho con trỏ đó NULL (nếu xóa đã tạo con trỏ NULL) và con trỏ khác sẽ là NULL và trỏ đến vị trí bộ nhớ miễn phí.

Giải pháp cho điều này nên là người dùng nên xóa tất cả các con trỏ trỏ đến cùng một vị trí. Bên trong nó nên kiểm tra xem bộ nhớ đã được giải phóng hơn không miễn phí. Chỉ làm cho con trỏ NULL.

Stroustrup có thể đã thiết kế xóa để hoạt động theo cách này. Anh ta nghĩ các lập trình viên sẽ chăm sóc điều này. Vì vậy, anh bỏ qua.

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