2014-10-03 14 views
41

Tôi đã nhận được một số mã C++ với các cấu trúc khác nhau được định nghĩa như thế này:Đây có phải là C++ destructor thừa không?

typedef struct _someStruct_ { 
    std::string someString; 
    std::vector<std::string> someVectorOfStrings; 
    int someOtherStuff; 

    ~_someStruct_() 
    { 
     someString.clear(); 
     someVectorOfStrings.clear(); 
    } 
} someStruct; 

là destructor đây hoàn toàn không cần thiết - nếu cấu trúc đã được destructed bởi destructor mặc định, sẽ không bất kỳ chuỗi, vectơ, vv vẫn bị phá hủy?

Nếu tôi viết mã, tôi sẽ không nghĩ đến việc thêm một trình phá hoại rõ ràng ở đây - tôi chỉ để trình biên dịch tiếp tục với nó. Khi tôi hiểu nó, thời gian duy nhất bạn có thể cần để tạo ra destructor của riêng bạn trong cấu trúc là nếu bất kỳ thành viên nào của cấu trúc chứa con trỏ đến dữ liệu có thể cần dọn dẹp, hoặc nếu một số chức năng bổ sung (vd gỡ lỗi, đăng nhập khi một cấu trúc bị xóa) là cần thiết.

Tôi có thiếu thứ gì đó ở đây không - có lý do nào tại sao chuỗi và vectơ đã được xóa rõ ràng trong trình hủy không? Nghi ngờ của tôi là người đã gửi cho tôi điều này thực sự là một lập trình viên C (xem typedef), người đã cố gắng biến một số mã C thành C++.

+9

Có, nó hoàn toàn vô dụng. Tuy nhiên, nếu vectơ đã được giữ nguyên con trỏ bạn phải gọi xóa mình trên mỗi con trỏ (tại thời điểm đó bạn nên sử dụng con trỏ thông minh). – Borgleader

+1

miễn là các destructors của các thành viên làm những gì là cần thiết, không có nhu cầu cho một destructor tùy chỉnh. –

+14

'typedef _someStruct_ {...} someStruct;' cũng hoàn toàn thừa, chỉ cần viết 'struct someStruct {...};'. Vì kiểu không thể hợp lệ trong một chương trình C (vì nó sử dụng một destructor) nên không có lý do gì để sử dụng một typedef cho tên struct. –

Trả lời

69

Có, trình hủy là hoàn toàn dư thừa.

Như bạn đã tự nói mã có các dấu hiệu cảnh báo khác. Ví dụ, việc sử dụng typedef struct không có ý nghĩa gì trong C++, nó là thừa như là destructor rỗng: Mã được viết bởi ai đó với một nắm bắt cận biên của C++, có ràng buộc phải có nhiều gotchas hơn (vì một điều, tên lớp là không hợp lệ do đến dấu gạch dưới hàng đầu trong phạm vi toàn cầu).

+3

Chờ đợi, điều đó không phải là dấu gạch dưới hàng đầu * theo sau là ký tự chữ hoa *? –

+5

@BartekBanachewicz xem http://stackoverflow.com/a/228797/981959 –

+0

@JonathanWakely Oh damn, giờ tôi hiểu rồi. Lỗi của tôi. –

49

Thực tế, đây là tồi tệ hơn đơn giản hơn bằng cách sử dụng trình phá hoại ngầm.

Bằng cách có trình phá hủy rõ ràng, trình biên dịch sẽ không cung cấp một hàm tạo di chuyển ngầm cho bạn!

20

Trình hủy gần như hoàn toàn dư thừa.

Có ba điều.

Đầu tiên, nó chặn việc tạo tự động các nhà xây dựng và chuyển nhượng bản sao/di chuyển. Điều này ... có thể không phải là một điều tốt. Nhưng có lẽ nó là mong muốn. Đó là, tuy nhiên, không giống như không ở đó.

Thứ hai, nó thay đổi thứ tự được làm sạch. Bộ đệm được giữ bởi chuỗi bị xóa, sau đó mỗi bộ đệm được giữ bởi các chuỗi trong vectơ bị phá hủy trong khi chuỗi giữ chúng bị hủy, sau đó vectơ một bộ đệm của bộ nhớ không sử dụng bị phá hủy (trả về bộ nhớ), sau đó chuỗi rỗng bây giờ bị phá hủy. Với một destructor mặc định, thứ tự là bộ đệm chuỗi của vector bị phá hủy, sau đó bộ nhớ cho chuỗi của vectơ được trả về trong khi vectơ bị hủy, sau đó chuỗi bị hủy cùng với bộ đệm của nó được trả về.

Bạn có thể phát hiện điều này với tình trạng quá tải phù hợp với nhà điều hành new & delete hoặc nếu bạn đã sử dụng trình phân bổ tùy chỉnh.

Cuối cùng, các trình phá hủy như vậy đôi khi có thể dễ dàng gỡ lỗi hơn, vì bạn có thể duyệt qua chúng.

Tuy nhiên, tỷ lệ cược là không có hiệu ứng tinh tế nào được nhà phát triển viết mã.

+0

Nó có thể làm gì để suy nghĩ về cơ học, các destructor mặc định có thể deallocate nhưng không "chà". Trong thực tế, tôi không chắc chắn rằng ngay cả xóa và rõ ràng sẽ rõ ràng không có vị trí dư thừa. Chúng tôi có thể không muốn bộ nhớ bị xước, ngay cả bộ nhớ chưa được phân bổ. – mckenzm

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