Tại sao không xóa đặt con trỏ thành NULL?


127

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 quan tâm thì nhiều sự cố do con trỏ không hợp lệ sẽ không xảy ra. Nhưng có nói rằng tôi có thể nghĩ ra một vài lý do tại sao tiêu chuẩn sẽ hạn chế điều này:

  1. Hiệu suất:

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

  2. Có thể là do constcon trỏ.

    Sau đó, một lần nữa tiêu chuẩn có thể đã làm một cái 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 cho việc không cho phép điều này?

Câu trả lời:


150

Stroustrup tự trả lời. Một đoạn trích:

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

Nhưng vấn đề chính mà ông nêu ra là lập luận xóa không cần phải là một giá trị.


Tôi nghĩ rằng điều này có thể sử dụng một số giải thích thêm. Tôi thậm chí không chắc anh ấy đang nói gì ... Tôi cho rằng tôi sẽ phải quay lại vào lúc sau khi tôi có thể dành một vài giờ để nghiên cứu điều này cho đến khi tôi nhận được nó. Hoặc, bạn có thể giải thích câu trả lời để giúp chúng tôi hiểu nhanh hơn.
Gabriel Staples

63

Đầu tiên, thiết lập thành null sẽ yêu cầu một biến được lưu trữ bộ nhớ. Điều đó đúng, rằng 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 tại một địa chỉ được tính toán. Điều đó là không thể với xóa "vô hiệu hóa".

Sau đó là hiệu suất. Bạn có thể đã viết mã theo cách mà con trỏ sẽ đi ra khỏi phạm vi ngay sau khi xóa xong. Làm đầy 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 ý thức hệ "không cần nó? Vậy thì bạn không phải trả tiền cho nó".

Nếu bạn cần sự an toàn, có một loạt các con trỏ thông minh phục vụ bạn hoặc bạn có thể tự viết - tốt hơn và thông minh hơn.


4
Địa chỉ được tính điểm tốt, ngay cả khi đó là thứ bạn không thường thấy
snemarch

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 tại một địa chỉ được tính toán. ???
Kẻ hủy diệt

@PravasiMeet Không, ý tôi làdelete (ptr + i)
sharptooth

39

Bạn có thể có nhiều con trỏ trỏ đến bộ nhớ đó. Nó sẽ tạo ra một cảm giác an toàn sai nếu con trỏ bạn chỉ định cho việc 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 có gì hơn một địa chỉ, một con 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ỏ để tìm những con trỏ đang tham chiếu cùng bộ nhớ mà bạn vừa xóa và cũng loại bỏ chúng. Sẽ rất khó tính khi quét tất cả các con trỏ cho địa chỉ đó và loại bỏ chúng, 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 các tham chiếu của chúng để thực hiện mục tiêu tương tự theo một cách khác.)


19

Một con trỏ có thể được lưu trong nhiều biến, đặt một trong số này thành NULL vẫn sẽ để lại các 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.

Ngoài ra, bạn có thể tạo chức năng của riêng mình, thực hiện những gì bạn muốn:

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

12

Bởi vì thực sự không cần thiết, và bởi vì nó sẽ yêu cầu xóa lấy con trỏ sang con trỏ thay vì chỉ con trỏ.


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

7

deleteđược sử dụng chủ yếu trong các hàm hủy, trong trường hợp này, việc đặt thành viên thành NULL là vô nghĩa. Một vài dòng sau, lúc đóng cửa }, thành viên không còn tồn tại. 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ẽ khiến mã sau đây bất hợp pháp:

T* const foo = new T;
delete foo;

6

Đâ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ó nên được đặt thành NULL? Bạn có thể khái quát điều này?


5

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


4

C ++ cho phép bạn xác định toán tử mới của riêng bạn và xóa để ví dụ họ sẽ sử dụng phân bổ nhóm của riêng bạn. Nếu bạn làm điều này thì 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 nhóm 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 bộ tự động NULL thành đố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 luôn luôn là NULL.


4

Triết lý của C ++ là "chỉ trả tiền nếu 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 mình, nó sẽ phục hồi 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 một vài biến - có thể không chỉ 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.


3

Tự động đặt con trỏ thành NULL 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. Sự cố duy nhất nó sẽ tránh là nếu bạn cố gắng xóa nó hai lần. Điều gì nếu bạn gọi một hàm thành viên trên một con trỏ như vậy? Nó vẫn sẽ sụp đổ (giả sử rằng nó truy cập các biến thành viên). C ++ không hạn chế bạn gọi bất kỳ chức năng nào trên con trỏ NULL, cũng không nên thực hiện điều đó theo quan điểm hiệu suất.


-1

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 như vậy có thể gây ra sự chậm trễ hiệu suất?

Một câu trả lời khác là chúng ta 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ỉ tạo ra con trỏ đó NULL (nếu xóa là tạo con trỏ NULL) và con trỏ khác sẽ không phải là NULL và trỏ đến vị trí bộ nhớ là miễn phí.

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

Stroustrup có thể đã thiết kế xóa để hoạt động theo cách này. Ông nghĩ rằng các lập trình viên sẽ chăm sóc điều này. Thế là anh mặc kệ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.