Xóa nullptr trong c ++ 0x có còn an toàn không?


84

Trong c++03nó là khá rõ ràng là việc xóa một con trỏ null không có tác dụng. Thật vậy, nó được tuyên bố rõ ràng §5.3.5/2rằng:

Trong một trong hai cách thay thế, nếu giá trị của toán hạng xóa là con trỏ null thì hoạt động không có hiệu lực.

Tuy nhiên, trong dự thảo hiện tại cho c++0xcâu này dường như bị thiếu. Trong phần còn lại của bản nháp, tôi chỉ có thể tìm thấy các câu nêu rõ điều gì sẽ xảy ra nếu toán hạng của biểu thức xóa không phải là hằng số con trỏ null. Việc xóa con trỏ null vẫn được xác định ở đâu c++0xvà nếu có thì ở đâu?

Ghi chú:

Có bằng chứng hoàn cảnh quan trọng cho thấy nó vẫn còn được xác định rõ.

Đầu tiên, có hai câu §5.3.5/2nói rằng

Trong phương án thay thế đầu tiên (đối tượng xóa), giá trị của toán hạng xóa có thể là giá trị con trỏ null, ...

Trong phương án thứ hai (xóa mảng), giá trị của toán hạng xóa có thể là giá trị con trỏ null hoặc ...

Những điều này nói rằng toán hạng được phép là null, nhưng tự chúng không thực sự xác định điều gì sẽ xảy ra nếu đúng như vậy.

Thứ hai, việc thay đổi ý nghĩa của delete 0là một thay đổi mang tính đột phá lớn, và ủy ban tiêu chuẩn sẽ rất khó thực hiện thay đổi cụ thể này. Hơn nữa, không đề cập đến việc đây là một thay đổi đột phá trong Phụ lục Tương thích (Phụ lục C) của c++0xdự thảo. Tuy nhiên, Phụ lục C là một phần Thông tin, vì vậy điều này không có nghĩa là không giải thích tiêu chuẩn.

Mặt khác, thực tế là việc xóa con trỏ null được yêu cầu không có hiệu lực ngụ ý kiểm tra thời gian chạy bổ sung. Trong rất nhiều mã, toán hạng không bao giờ có thể là giá trị rỗng, vì vậy việc kiểm tra thời gian chạy này mâu thuẫn với nguyên tắc chi phí bằng không. Có thể ủy ban vừa quyết định thay đổi hành vi để mang lại chuẩn c ++ phù hợp hơn với các mục tiêu thiết kế đã nêu của ngôn ngữ.

Câu trả lời:


101

5.3.5 / 7 cho biết:

Nếu giá trị của toán hạng của biểu thức xóa không phải là giá trị con trỏ null, biểu thức xóa sẽ gọi một hàm thỏa thuận (3.7.4.2). Nếu không, không xác định được liệu hàm thỏa thuận có được gọi hay không.

Và 3.7.4.2/3 cho biết:

Giá trị của đối số đầu tiên được cung cấp cho một hàm thỏa thuận có thể là một giá trị con trỏ null; nếu vậy, và nếu hàm deallocation là một hàm được cung cấp trong thư viện chuẩn, thì lệnh gọi không có hiệu lực.

Vì vậy, hành vi được xác định rõ ràng, miễn là hàm thỏa thuận tiêu chuẩn được sử dụng hoặc một hàm thỏa thuận do người dùng cung cấp xử lý con trỏ rỗng một cách chính xác.


9
Vì C ++ 14 "Nếu biểu thức đánh giá là giá trị con trỏ null, không có hàm hủy nào được gọi và hàm thỏa thuận không được gọi."
Wormer

2
@Wormer Tôi không nghĩ rằng trang đó là chính xác. Tiêu chuẩn C ++ 14 vẫn cho biết "không xác định được liệu hàm thỏa thuận có được gọi hay không" khi con trỏ là null (5.3.5 / 7).
giữa

1
Ngoài ra, không an toàn khi gọi fclose () cho con trỏ tệp null. Trên Ubuntu (và có lẽ cả các hệ điều hành khác), fclose (NULL) gây ra lỗi phân đoạn.
Gerry Beauregard

7

Mặt khác, thực tế là việc xóa con trỏ null được yêu cầu không có hiệu lực ngụ ý kiểm tra thời gian chạy bổ sung.

Cách diễn đạt mới không xóa kiểm tra thời gian chạy đó cho con trỏ null. Ngược lại: tiêu chuẩn dự thảo thậm chí còn gần hơn với việc nói rằng một triển khai phải thực hiện kiểm tra con trỏ null để tuân thủ.

Cũng đáng chú ý: Tiêu chuẩn cũ mâu thuẫn với chính nó ở chỗ nó nói (5.3.5 / 2) rằng "nếu giá trị của toán hạng xóa là con trỏ null thì hoạt động không có hiệu lực" nhưng sau đó nói rằng (5.3.5 / 7) "biểu thức xóa sẽ gọi một hàm định vị." Gọi một hàm là một hiệu ứng. Điều này đặc biệt như vậy vì hàm được gọi có thể là một hàm bị ghi đè operator delete.

Cách diễn đạt mới loại bỏ mâu thuẫn đó, rõ ràng để nó tùy thuộc vào việc triển khai cho dù hàm deallocation có được gọi trong trường hợp xóa con trỏ null hay không.

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.