2010-08-07 31 views
24

Dưới đây là một số mẫu mã mà tôi có:Xóa một đối tượng trong C++

void test() 
{ 
    Object1 *obj = new Object1(); 
    . 
    . 
    . 
    delete obj; 
} 

tôi chạy nó trong Visual Studio, và nó bị treo ở phù hợp với 'xóa obj;'. Đây có phải là cách bình thường để giải phóng bộ nhớ liên kết với một đối tượng không? Tôi nhận ra rằng nó tự động gọi destructor ... điều này có bình thường không?


Đây là một đoạn mã:.

if(node->isleaf()) 
    { 
     vector<string> vec = node->L; 
     vec.push_back(node->code); 
     sort(vec.begin(), vec.end()); 

     Mesh* msh = loadLeaves(vec, node->code); 

     Simplification smp(msh); 

     smp.simplifyErrorBased(errorThreshold); 

     int meshFaceCount = msh->faces.size(); 

     saveLeaves(vec, msh); 

     delete msh; 
    } 

loadleaves() là một chức năng mà đọc một lưới từ đĩa và tạo ra một đối tượng Mesh và trả về nó (nghĩ về vecnode->code chỉ là thông tin về mở tệp)

Tôi có nên xóa dòng delete msh; không?

+3

cho phép xem lớp học của bạn trông như thế nào. bạn có thể có cái gì đó sai với destructor của bạn. – TheFuzz

+0

Chức năng 'loadLeaves' được đề cập dưới đây có phân bổ đối tượng trên heap không? hoặc nó trả lại địa chỉ của một địa phương hoặc một cái gì đó như thế? hãy nhớ rằng, bạn chỉ có thể 'xóa' những gì bạn' mới' ... –

+0

Hãy chắc chắn rằng destructor không phải là riêng tư! – Vaibhav

Trả lời

32

Đây không phải là cách bình thường để giải phóng bộ nhớ liên kết với một đối tượng?

Đây là cách phổ biến để quản lý bộ nhớ được cấp phát động, nhưng đó không phải là cách hay để làm như vậy. Loại mã này là dễ vỡ vì nó không phải là ngoại lệ an toàn: nếu một ngoại lệ được ném giữa khi bạn tạo đối tượng và khi bạn xóa nó, bạn sẽ làm rò rỉ đối tượng đó. Sử dụng một hộp chứa con trỏ thông minh, bạn có thể sử dụng nó để có được quản lý tài nguyên giới hạn phạm vi (thường được gọi là resource acquisition is initialization hoặc RAII) tốt hơn rất nhiều.

Như một ví dụ về quản lý tài nguyên tự động:

void test() 
{ 
    std::auto_ptr<Object1> obj1(new Object1); 

} // The object is automatically deleted when the scope ends. 

Tùy thuộc vào trường hợp sử dụng của bạn, auto_ptr có thể không cung cấp ngữ nghĩa mà bạn cần. Trong trường hợp đó, bạn có thể xem xét sử dụng shared_ptr.

Vì lý do chương trình của bạn gặp sự cố khi bạn xóa đối tượng, bạn không có đủ mã để mọi người có thể trả lời câu hỏi đó một cách chắc chắn.

2

nếu nó gặp sự cố trên đường dây delete thì bạn gần như chắc chắn đã làm hỏng heap. Chúng tôi sẽ cần phải xem thêm mã để chẩn đoán vấn đề vì ví dụ bạn trình bày không có lỗi.

Có lẽ bạn có tràn bộ đệm trên heap đã làm hỏng cấu trúc heap hoặc thậm chí một cái gì đó đơn giản như một "đôi miễn phí" (hoặc trong trường hợp c + + "xóa kép").

Ngoài ra, như Fuzz đã lưu ý, bạn cũng có thể gặp lỗi trong trình phá hủy của mình. Và có, nó là hoàn toàn bình thường và mong đợi cho delete để gọi destructor, đó là trong thực tế, một trong hai mục đích của nó (gọi destructor sau đó bộ nhớ miễn phí).

3

Đây không phải là cách bình thường để giải phóng bộ nhớ được liên kết với một đối tượng?

Vâng, đúng vậy.

Tôi nhận ra rằng nó tự động gọi trình phá hủy ... điều này có bình thường không?

Yes

Hãy chắc chắn rằng bạn đã không double delete đối tượng của bạn.

+1

Vì vậy, tại sao điều này lại bình thường? Vì nó là một biến con trỏ, làm thế nào là bình thường này để có được xóa tự động? Điều gì xảy ra trước tiên tôi xóa đối tượng và sau đó chạm vào dòng '}', nó lại gọi hàm hủy, điều này gây ra sự cố. Câu hỏi của tôi là tại sao nó lại tự động gọi hàm hủy? Nếu nó là bình thường, thì tại sao mọi người xóa một đối tượng trong trường hợp này? – Nima

+1

Đọc các phần sau: http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.9 và http://www.parashift.com/c++-faq-lite/freestore-mgmt.html# faq-16.9 'Sau đó, trình hủy diệt Fred :: ~ Fred() sẽ * tự động * được gọi khi bạn xóa ......' Hiển thị cho chúng tôi mã hoàn chỉnh. –

6

Mã của bạn thực sự đang sử dụng cách thông thường để tạo và xóa đối tượng động. Có, nó hoàn toàn bình thường (và thực sự được đảm bảo bởi tiêu chuẩn ngôn ngữ!) Rằng delete sẽ gọi hàm hủy của đối tượng, giống như new phải gọi hàm tạo.

Nếu bạn không instantiating Object1 trực tiếp nhưng một số lớp con của chúng, tôi muốn nhắc nhở bạn rằng bất kỳ lớp học dự định sẽ được thừa hưởng từ phải có một ảo destructor (để destructor phân lớp đúng có thể được áp dụng trong các trường hợp tương tự với mã mẫu này, nhưng nếu mã mẫu của bạn thực sự là đại diện cho mã thực tế của bạn, điều này không thể là vấn đề hiện tại của bạn - phải là một thứ khác, có thể trong mã hủy bạn không hiển thị cho chúng tôi, hoặc một số tham nhũng mã bạn không hiển thị trong hàm đó hoặc mã mà nó gọi ...?

BTW, nếu bạn luôn xóa đối tượng ngay trước khi thoát khỏi chức năng khởi tạo, không có điểm nào làm cho đối tượng đó động - chỉ cần khai báo nó dưới dạng địa phương (lớp lưu trữ auto, như là mặc định) biến của chức năng đã nói!

1

saveLeaves(vec,msh);
Tôi giả định lấy con trỏ msh và đặt con trỏ vào bên trong vec. Kể từ msh chỉ là một con trỏ đến bộ nhớ, nếu bạn xóa nó, nó cũng sẽ bị xóa bên trong của vectơ.

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