2008-11-19 16 views
6

Tôi biết rằng tôi phải sử dụng delete [] sau khi tôi sử dụng new [], vì vậy việc sử dụng auto_ptr với new [] không phải là một ý tưởng sáng sủa.xóa và xóa [] giống nhau trong Visual C++?

Tuy nhiên, trong khi gỡ lỗi delete [] (sử dụng Visual Studio 2005), tôi nhận thấy rằng các cuộc gọi đi vào một chức năng trông như thế này:

void operator delete[](void * p) 
{ 
    RTCCALLBACK(_RTC_Free_hook, (p, 0)) 
    operator delete(p); 
} 

Điều này có nghĩa, cú pháp [] bị mất trên Visual C++? Nếu vậy, tại sao? Là nó để làm giảm các nhà phát triển từ gánh nặng của việc ghi nhớ cú pháp đúng?

+0

'xóa [] p' KHÔNG tương đương với' toán tử xóa [] (p) '. –

Trả lời

26

xem xét mã này:

class DeleteMe 
{ 
public: 
    ~DeleteMe() 
    { 
    std::cout << "Thanks mate, I'm gone!\n"; 
    } 
}; 

int main() 
{ 
    DeleteMe *arr = new DeleteMe[5]; 
    delete arr; 
    return 0; 
} 

Nếu bạn chạy mà trong VS2005 nó sẽ in:

Thanks mate, I'm gone!

Nếu bạn thay đổi main() tuân thủ một cách chính xác để cáC++ tiêu chuẩn C:

int main() 
{ 
    DeleteMe *arr = new DeleteMe[5]; 
    delete[] arr; 
    return 0; 
} 

Nó sẽ in:

Thanks mate, I'm gone! 
Thanks mate, I'm gone! 
Thanks mate, I'm gone! 
Thanks mate, I'm gone! 
Thanks mate, I'm gone!

Đừng bắn mình vào chân. VS2005 sẽ KHÔNG làm điều đúng nếu bạn không phù hợp với các hương vị khác nhau của mới/xóa. Sẽ không có trình biên dịch tuân thủ chuẩn C++ nào khác.

Có một số phép thuật biên dịch xảy ra xung quanh operator newoperator delete (và các hương vị khác nhau của chúng), về cơ bản cuộc gọi tới các ctors và dtors được thêm vào hậu trường. Phép thuật này phụ thuộc vào những dấu ngoặc nhỏ [], vì vậy đừng đánh mất chúng hoặc bạn sẽ mất phép thuật.

+0

OK, tôi chấp nhận rằng nó được thực hiện thông qua phép thuật. :) –

2

Chỉ vì chúng có thể hoạt động giống nhau, không có nghĩa là bạn nhất thiết có thể đối xử với chúng giống nhau - hành vi có thể thay đổi. Và bên cạnh đó, những người quan tâm - bạn nên viết mã của bạn để bạn không cần phải nhớ.

Ngoài ra, bạn có thể sử dụng scoped_array để xóa mảng.

+0

Tôi biết, chúng tôi nên, nhưng cho đến nay chúng tôi không sử dụng Boost.:( –

+0

Tôi tin rằng scoped_array (và các loại con trỏ thông minh Boost) là một phần của TR1.Bạn có thể đã có chúng mà không cần tăng cường – Ferruccio

+0

Tôi bị mất một phần về VS2005.Tôi nghĩ rằng TR1 là trong VS2008 SP1 – Ferruccio

4

Tôi đoán đó chỉ là chi tiết triển khai. Trình phân bổ heap của chúng hoạt động theo cùng cách khi giải phóng mảng và con trỏ.

Nhưng vì tiêu chuẩn cho phép triển khai có các thuật toán khác nhau cho hai trường hợp, bạn thực sự không nên giả định rằng deletedelete[] cũng làm như vậy. Hành vi này thậm chí có thể thay đổi giữa các phiên bản trình biên dịch.

2

Có lẽ dữ liệu bạn đã xóa không có trình phá hủy? Nếu vậy, việc xóa đơn giản này sẽ có ý nghĩa. Nó đang làm việc trên void * sau khi tất cả.

Dù sao, bạn phải sử dụng xóa [] để đảm bảo rằng trình phá hủy được chạy cho từng phần tử trong mảng.

2

Xóa mảng không có [] sẽ chỉ giải phóng bộ nhớ, nhưng sẽ KHÔNG gọi hàm hủy trong mỗi đối tượng trong mảng. Vì vậy, về mặt kỹ thuật bạn chỉ cần [] nếu destructor của bạn cần phải được gọi.

+0

Tôi chắc chắn sẽ sửa đổi đầu tiên của bạn tuyên bố vì nó không chính xác và nguy hiểm ngay cả khi bạn đưa ra một lời giải thích chính xác ở cuối. –

+0

Bạn đúng, VS 2005 thực sự quan tâm và họ thậm chí còn phát hiện ra vấn đề trong thời gian chạy. đoán MS đã thay đổi nó –

+0

Nếu bạn bỏ qua '[]', bạn triệu hồi quỷ mũi. –

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