2010-10-23 39 views
11

Tôi có đoạn code sau, không biên dịch:Tôi làm cách nào để hủy bỏ phiên bản xóa?

int *p = new(nothrow) int; 
delete (nothrow) p; //Error 

Các lỗi tôi nhận được là:

lỗi C2440: 'xóa': không thể chuyển đổi từ 'std :: const nothrow_t' thành 'void *'

Có phải phiên bản nothrow của delete không? Nếu vậy, làm thế nào tôi có thể gọi nó?


Trong C++: Tham khảo đầy đủ, có sẵn nhưng tôi thấy các ý kiến ​​khác nhau trực tuyến, do đó sự nhầm lẫn.

MSDN cũng nói về sự tồn tại của nó, nhưng tôi không thể tìm thấy cách nó có thể được sử dụng trong mã.

Here, một số người nói rằng không có thứ gì như vậy.

+0

Liên kết MSDN của bạn nói về sự tồn tại của 'nothrow', nhưng * that * không bao giờ nghi ngờ gì. Đó là * 'delete' * mà mọi người nói rằng bạn không có phiên bản 'nothrow', và họ nói đúng. –

+3

Nếu cuốn sách đó là cuốn sách Schildt, bạn nên (không may) ném nó đi. Anh chàng đó thật khủng khiếp, và không biết anh ấy đang nói gì khi nói đến ngôn ngữ. – GManNickG

Trả lời

15

A std::nothrow_t chức năng deallocation tồn tại, nhưng bạn không thể gọi nó với biểu thức delete.

Chức năng deallocation có sẵn để hoàn thành. Nếu biểu thức new không thành công do ngoại lệ, trình biên dịch cần giải phóng bộ nhớ được phân bổ qua operator new với một số khớp với gọi tới operator delete. Vì vậy, cần phải có một số operator delete chấp nhận std::nothrow_t, để cho phép điều này.

(Nghĩa là, nói chung, một biểu new với hình thức new (args...) T sẽ phân bổ bộ nhớ với một cuộc gọi đến operator new(sizeof(T), args...). Để "trận đấu" có nghĩa là để gọi operator delete với những lập luận tương tự, ngoại trừ người đầu tiên.)

Note bạn có thể gọi trực tiếp cho nhà điều hành: operator delete(memory, std::nothrow);. Tuy nhiên, một biểu thức delete không bao giờ gọi hàm deallocation chung với các tham số bổ sung.


Vì vậy, bạn có thể "gọi" nó với:

struct always_throw 
{ 
    always_throw() { throw std::exception(); } 
}; 

new (std::nothrow) always_throw; 

Tại một số điểm, điều này sẽ cấp phát bộ nhớ với một cuộc gọi đến:

void* __memory = operator new(sizeof(always_throw), std::nothrow); 

Kể từ khi khởi tạo của đối tượng ném , trình biên dịch cần giải phóng bộ nhớ được cấp phát bằng chức năng deallocation phù hợp, do đó, nó có:

operator delete(__memory, std::nothrow); 

Gọi phiên bản std::nothrow_t.

5

Không có hình thức như vậy delete, vì delete không ném, vì:

  1. Nó thực hiện không phân bổ.
  2. Nó thường được sử dụng trong destructors mà không nên ném!

Các mục được tạo bằng phiên bản nothrow mới sẽ trả về NULL thay vì ném ngoại lệ bad_alloc. Sử dụng delete trên NULL là hoàn toàn hợp lệ, vì vậy không có tình huống mà nó nên ném.

+0

Ồ. Nhưng trong tài liệu tham khảo đầy đủ C++, nó cho rằng nó tồn tại và tôi thấy các ý kiến ​​khác nhau khác nhau trên internet, do đó sự nhầm lẫn. – bjskishore123

+1

Ý của bạn là "chúng không được phân bổ từ đống"? Nó vẫn phân bổ bộ nhớ, nó sẽ không ném nếu nó không thể. – GManNickG

+0

Xin lỗi, cập nhật để ít gây nhầm lẫn và không gây nhầm lẫn với tại chỗ mới ... –

2

Đối với hầu hết các mục đích thực tế, chỉ có một phiên bản xóa. Các new(nothrow) được viết như là một nhà điều hành vị trí mới, nhưng đối với hầu hết các phần, không có phiên bản tương ứng cho xóa. Ngoại lệ duy nhất là phiên bản xóa được gọi khi một vị trí mới ném - nhưng vì (trong trường hợp này) bạn đã đảm bảo rằng new không thể ném, phiên bản xóa đó không thực sự sử dụng/trợ giúp đây.

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