2011-06-28 27 views
8

Tôi có mã sau đây và tôi tự hỏi liệu delete b có cần thiết ở đây không? Hệ điều hành của tôi có tự động xóa vùng bộ nhớ được cấp không?Xóa có cần thiết trong một destructor?

class A 
{ 
    B *b; 

    A() 
    { 
     b = new B(); 
    } 

    ~A() 
    { 
     delete b; 
    } 
}; 

Rất cám ơn.

+5

['A' cũng cần một trình tạo bản sao và toán tử gán) (http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). – GManNickG

Trả lời

10

Vâng, bạn phải delete mọi đối tượng được tạo ra với newmà bạn sở hữu. Trong trường hợp này, có vẻ như class A sở hữu chính trường hợp đó là class B và chịu trách nhiệm gọi số delete.

Bạn sẽ sử dụng con trỏ thông minh hơn để quản lý thời gian hoạt động của class B. Cũng lưu ý rằng bạn phải thực hiện hoặc cấm phép toán gán và sao chép hàm khởi tạo trong class A để ngăn không cho sao chép nông đối tượng sẽ gây ra nhiều rắc rối cho bạn.

1

Chắc chắn là cần thiết theo cách bạn đã viết. Ngay cả với delete, mặc dù, lớp học về cơ bản bị phá vỡ vì nó quản lý một nguồn tài nguyên nhưng không tuân theo the rule of three.

Điều đó nói rằng, hầu như chắc chắn không có lý do gì để quản lý bộ nhớ thủ công - hiếm khi xảy ra. Đó là khả năng mà bạn nên hoặc là chỉ có một đối tượng B như là một biến thành viên, hoặc bạn nên sử dụng một con trỏ thông minh, giống như QScopedPointer:

struct A 
{ 
    QScopedPointer<B> b; 
    A() : b(new B()) { } 

    // No ~A() needed; when the A object is destroyed, QScopedPointer ensures 
    // that the B object pointed to by the member 'b' is destroyed and deleted. 
}; 

Bạn sẽ muốn chắc chắn rằng bạn có a good introductory C++ book để bạn có thể tìm hiểu cách viết các chương trình C++ chính xác.

5

Có thể hệ điều hành của bạn sẽ giải phóng bộ nhớ được cấp phát - nhưng điều này được thực hiện khi chương trình của bạn thoát. Các chương trình chạy dài sẽ chạy vào các vấn đề về bộ nhớ.

Bạn nên sử dụng con trỏ thông minh cho các đối tượng được phủ tự động. Đây sẽ làm tất cả các công cụ xóa cho bạn.

  • std :: auto_ptr
  • tăng :: shared_ptr
  • boost :: scoped_ptr
1

Nó sẽ rõ ràng khu vực này chỉ khi quá trình này kết thúc, nhưng khu vực này sẽ vẫn được phân bổ tất cả các thời gian cho đến lúc đó, có nghĩa là memory leak.

2

Nếu bạn gọi một lần xóa mới, tương ứng luôn được khuyến khích.

Theo như hệ điều hành xóa bộ nhớ của bạn .. có, nó sẽ xảy ra nhưng chỉ sau khi toàn bộ quá trình chấm dứt (ví dụ: ứng dụng của bạn thoát). Chỉ khi đó tất cả bộ nhớ và các tài nguyên khác được hệ điều hành thu hồi.

Thứ ba, hãy thử sử dụng mới/chỉ xóa khi cần. Trong trường hợp của bạn, bạn chỉ có thể viết

class A 
{ 

B b; 

    A() {} 

    ~A() {} 

}; 

Nó sẽ có tác dụng tương tự và bạn tránh phân bổ bộ nhớ động.

0

Thành viên b sẽ được cấp phát trên heap. Đúng là hệ điều hành sẽ giải phóng tất cả bộ nhớ bị chiếm bởi đống; tuy nhiên điều đó sẽ chỉ xảy ra một lần: khi thoát chương trình. Vì vậy, nếu bạn không giải phóng khối heap được phân bổ trong thời gian chúng trở nên không được sử dụng (thường là trong destructor của một số đối tượng), bạn đang mạo hiểm để có được một memory leak. Vì vậy, câu trả lời về cơ bản là: yes, bạn phải gọi delete theo cách thủ công, vì bộ nhớ sẽ không được giải phóng ASAP tự động (mặc dù con trỏ thông minh sẽ giúp bạn đạt được điều gì đó tương tự).

0

Mọi thứ bạn phân bổ với new bạn nên miễn phí với delete, nếu không có rò rỉ bộ nhớ trong ứng dụng của bạn.

Trên hầu hết các hệ điều hành hiện đại (chắc chắn là hệ điều hành mà mọi người thường chạy trên máy tính để bàn), mọi thứ mà quá trình sử dụng sẽ được dọn sạch khi quá trình kết thúc, vì vậy nếu bạn quên delete thì bộ nhớ sẽ được giải phóng. Nhưng bạn nên dựa vào điều này.

Cách đây lâu tôi lập trình trên Amiga trong C. Hệ điều hành của nó kém phức tạp hơn nhiều so với hệ điều hành hiện tại. Nếu bạn cấp phát bộ nhớ và không giải phóng bộ nhớ, nó sẽ vẫn được cấp phát cho đến khi bạn tắt hoặc khởi động lại máy tính, ngay cả sau khi quá trình kết thúc. Rò rỉ bộ nhớ là một vấn đề nghiêm trọng hơn nữa.

1

Quản lý tài nguyên không chỉ là giải phóng bộ nhớ. Có, hầu hết các nền tảng sẽ làm cho bất kỳ bộ nhớ nào bạn phân bổ khi quá trình kết thúc và bộ nhớ đủ rẻ để có thể bạn sẽ không nhận thấy trong một thời gian. Nhưng những gì về tập tin b là giữ mở, hoặc mutex nó sẽ mở khóa trong destructor của nó? Trước khi bạn hết bộ nhớ, bạn có thể gặp phải các vấn đề từ việc cho phép các đối tượng của bạn sống trong quá khứ của họ.

0

1) Các ứng dụng chạy dài sẽ gặp sự cố, vì hệ điều hành chỉ có thể lấy lại bộ nhớ khi ứng dụng ngừng chạy.

2) delete b; cũng làm cho trình phá hủy của cá thể B được chỉ định chạy. Nếu không nó sẽ không bao giờ chạy, vì không còn cách nào để có được nó. Rằng destructor có thể làm điều gì đó quan trọng.

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