2012-05-05 40 views
31

Tôi hoàn toàn bối rối về việc xóa bỏ mọi thứ trong C++ Nếu tôi khai báo một mảng đối tượng và nếu tôi sử dụng hàm clear(). Tôi có thể chắc chắn rằng bộ nhớ đã được phát hành?C++ xóa vector, đối tượng, bộ nhớ miễn phí

Ví dụ:

tempObject obj1; 
tempObject obj2; 
vector<tempObject> tempVector; 

tempVector.pushback(obj1); 
tempVector.pushback(obj2); 

Tôi có thể một cách an toàn gọi rõ ràng để giải phóng tất cả các bộ nhớ? Hay tôi cần lặp lại để xóa từng cái một?

tempVector.clear(); 

Nếu trường hợp này được thay đổi thành con trỏ của đối tượng, câu trả lời có giống như trên không?

+1

Không có gì khác biệt so với trường hợp thứ hai so với trường hợp đầu tiên ngoài thực tế nó chỉ một vectơ. Tôi nghĩ rằng câu hỏi này nên được mở rộng để bạn có được một nắm bắt về cách phân bổ bộ nhớ/deallocation nên làm việc, và có lẽ con trỏ quá. – Marlon

+0

Điều này nói rằng tuyên bố nó bên trong một chồng chức năng tự động gọi destructor lúc đóng cửa. https://stackoverflow.com/questions/3054567/right-way-to-deallocate-an-stdvector-object –

Trả lời

62

Bạn có thể gọi rõ ràng và điều đó sẽ phá hủy tất cả các đối tượng, nhưng điều đó sẽ không giải phóng bộ nhớ. Looping qua các yếu tố cá nhân sẽ không giúp được gì (những hành động bạn sẽ thậm chí đề nghị xử lý đối tượng?) Những gì bạn có thể làm điều này là:

vector<tempObject>().swap(tempVector); 

Điều đó sẽ tạo ra một vector rỗng không có bộ nhớ phân bổ và trao đổi nó với tempVector, giải quyết hiệu quả bộ nhớ.

C++ 11 cũng có chức năng shrink_to_fit, bạn có thể gọi sau cuộc gọi để xóa() và về mặt lý thuyết sẽ thu nhỏ dung lượng để vừa với kích thước (bây giờ là 0). Tuy nhiên, đây là một yêu cầu không ràng buộc và việc triển khai của bạn là miễn phí để bỏ qua nó.

+0

Xin cảm ơn vì đã trả lời. bạn có thể giải thích những gì ở trên không? sau khi gọi điều đó, tôi có cần phải gọi rõ không? – mister

+3

@dupdupdup: Không, bạn không cần phải gọi rõ ràng. Các đối tượng trong tempVector được chuyển tới vector trống. Sau đó, các vector trống, vì nó là một đối tượng tạm thời không tên, bị phá hủy, và nội dung của nó, mà trước đó thuộc sở hữu của tempVector, bị phá hủy và bộ nhớ deallocated. –

+0

Tôi không có chuyên gia C++ nào, tâm trí giải thích cách thức này tốt hơn 'tempVector.resize (0)' trước tiên tôi sẽ thử? – delnan

14

vector::clear() không giải phóng bộ nhớ được phân bổ bởi vectơ để lưu trữ các đối tượng; nó gọi destructors cho các đối tượng mà nó nắm giữ.

Ví dụ, nếu vector sử dụng một mảng như một cửa hàng ủng hộ và hiện đang chứa 10 nguyên tố, sau đó gọi clear() sẽ gọi destructor của từng đối tượng trong mảng, nhưng mảng ủng hộ sẽ không được deallocated, do đó vẫn là sizeof(T) * 10 byte được phân bổ cho vectơ (ít nhất). size() sẽ là 0, nhưng size() trả lại số phần tử trong vectơ, không nhất thiết là kích thước của cửa hàng sao lưu.

Đối với câu hỏi thứ hai của bạn, bất cứ điều gì bạn phân bổ với new bạn phải deallocate với delete. Bạn thường không duy trì một con trỏ đến một vectơ vì lý do này. Có rất ít (nếu có) là một lý do chính đáng để làm điều này và bạn ngăn không cho vectơ bị làm sạch khi nó rời khỏi phạm vi. Tuy nhiên, gọi số clear() sẽ vẫn hoạt động theo cùng một cách bất kể nó được phân bổ như thế nào.

18

Có hai điều riêng biệt ở đây:

  1. đối tượng đời
  2. thời gian lưu trữ

Ví dụ:

{ 
    vector<MyObject> v; 
    // do some stuff, push some objects onto v 
    v.clear(); // 1 
    // maybe do some more stuff 
} // 2 

Tại 1, bạn rõ ràng v: này phá hủy tất cả các đối tượng mà nó đang lưu trữ. Mỗi người được gọi là destructor của nó, nếu bạn đã viết một, và bất cứ điều gì thuộc sở hữu của rằng MyObject bây giờ được phát hành. Tuy nhiên, vector v có quyền giữ bộ nhớ thô trong trường hợp bạn muốn sau này.

Nếu bạn quyết định đẩy một số thứ khác vào giữa 12, điều này tiết kiệm thời gian vì nó có thể sử dụng lại bộ nhớ cũ.

Tại 2, vector v đi ra khỏi phạm vi: bất kỳ đối tượng bạn đẩy vào nó từ 1 sẽ bị phá hủy (như nếu bạn muốn một cách rõ ràng được gọi là rõ ràng một lần nữa), nhưng bây giờ việc lưu trữ cơ bản cũng được phát hành (v won' t xung quanh để tái sử dụng nó nữa).


Nếu tôi thay đổi ví dụ cái v trở thành một con trỏ, bạn cần phải xóa nó một cách rõ ràng, như con trỏ đi ra khỏi phạm vi ở 2 không làm điều đó cho bạn. Tốt nhất bạn nên sử dụng một cái gì đó như std::unique_ptr trong trường hợp đó, nhưng nếu bạn không và v bị rò rỉ, dung lượng lưu trữ được phân bổ cũng sẽ bị rò rỉ. Như trên, bạn cần đảm bảo rằng v bị xóa và gọi số clear là không đủ.

+0

Bạn có ý gì khi 'Nếu bạn quyết định đẩy .. điều này tiết kiệm thời gian vì nó có thể tái sử dụng bộ nhớ cũ.'? Tại sao bộ nhớ cũ lại quan trọng khi bạn muốn thêm các mục mới? – user13107

+0

Vectơ phải quản lý lưu trữ nội bộ cho các đối tượng mà nó lưu trữ. Việc tạo một vectơ mới yêu cầu phân bổ bộ nhớ mới, nhưng việc xóa và sử dụng lại một vectơ hiện có cho phép (nhưng không đảm bảo) sử dụng lại bộ nhớ đã được phân bổ của nó. – Useless

0

Nếu bạn cần sử dụng véc-tơ lặp đi lặp lại và mã hiện tại của bạn khai báo nó lặp đi lặp lại trong vòng lặp hoặc trên mọi cuộc gọi hàm, có khả năng bạn sẽ hết bộ nhớ. Tôi đề nghị bạn nên khai báo nó bên ngoài, vượt qua chúng như con trỏ trong các chức năng của bạn và sử dụng:

my_arr.resize() 

Bằng cách này, bạn tiếp tục sử dụng trình tự bộ nhớ tương tự cho vectơ của bạn thay vì yêu cầu cho chuỗi mới mỗi lần. Hy vọng điều này sẽ hữu ích. Lưu ý: thay đổi kích thước thành các kích thước khác nhau có thể thêm các giá trị ngẫu nhiên. Vượt qua một số nguyên như 0 để khởi tạo chúng, nếu được yêu cầu.

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