简体   繁体   English

C++ 删除向量、对象、空闲内存

[英]C++ delete vector, objects, free memory

I am totally confused with regards to deleting things in C++.我对在 C++ 中删除东西感到非常困惑。 If I declare an array of objects and if I use the clear() member function.如果我声明了一个对象数组并且我使用了clear()成员函数。 Can I be sure that the memory was released?我能确定内存被释放了吗?

For example :例如 :

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

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

Can I safely call clear to free up all the memory?我可以安全地调用 clear 来释放所有内存吗? Or do I need to iterate through to delete one by one?还是需要遍历一遍才能删除?

tempVector.clear();

If this scenario is changed to a pointer of objects, will the answer be the same as above?如果把这个场景换成一个对象的指针,答案会不会和上面一样?

vector<tempObject> *tempVector;
//push objects....
tempVector->clear();

You can call clear, and that will destroy all the objects, but that will not free the memory.您可以调用 clear,这将销毁所有对象,但不会释放内存。 Looping through the individual elements will not help either (what action would you even propose to take on the objects?) What you can do is this:循环遍历各个元素也无济于事(您甚至建议对对象采取什么行动?)您可以做的是:

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

That will create an empty vector with no memory allocated and swap it with tempVector, effectively deallocating the memory.这将创建一个没有分配内存的空向量,并将其与 tempVector 交换,从而有效地释放内存。

C++11 also has the function shrink_to_fit , which you could call after the call to clear(), and it would theoretically shrink the capacity to fit the size (which is now 0). C++11 也有函数shrink_to_fit ,你可以在调用 clear() 之后调用它,理论上它会缩小容量以适应大小(现在是 0)。 This is however, a non-binding request, and your implementation is free to ignore it.然而,这是一个非绑定请求,您的实现可以随意忽略它。

There are two separate things here:这里有两件事:

  1. object lifetime对象生命周期
  2. storage duration储存期限

For example:例如:

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

At 1 , you clear v : this destroys all the objects it was storing.1 ,您清除v :这会破坏它存储的所有对象。 Each gets its destructor called, if your wrote one, and anything owned by that MyObject is now released.每个都调用它的析构函数,如果你写了一个,那么MyObject拥有的任何东西现在都被释放了。 However , vector v has the right to keep the raw storage around in case you want it later.但是,vector v有权保留原始存储,以备日后使用。

If you decide to push some more things into it between 1 and 2 , this saves time as it can reuse the old memory.如果您决定在12之间将更多内容推入其中,则可以节省时间,因为它可以重用旧内存。

At 2 , the vector v goes out of scope: any objects you pushed into it since 1 will be destroyed (as if you'd explicitly called clear again), but now the underlying storage is also released ( v won't be around to reuse it any more).2 ,向量v超出范围:从1推入它的任何对象都将被销毁(就像您再次明确调用 clear 一样),但现在底层存储也被释放( v不会出现在再使用它)。


If I change the example so v becomes a pointer to a dynamically-allocated vector, you need to explicitly delete it, as the pointer going out of scope at 2 doesn't do that for you.如果我更改示例,使v成为指向动态分配向量的指针,则您需要显式删除它,因为在2处超出范围的指针不会为您执行此操作。 It's better to use something like std::unique_ptr in that case, but if you don't and v is leaked, the storage it allocated will be leaked as well.在这种情况下最好使用std::unique_ptr类的东西,但如果你不这样做并且v被泄露,它分配的存储也会被泄露。 As above, you need to make sure v is deleted, and calling clear isn't sufficient.如上所述,您需要确保v被删除,并且调用clear是不够的。

vector::clear() does not free memory allocated by the vector to store objects; vector::clear()不会释放 vector 分配的内存来存储对象; it calls destructors for the objects it holds.它为它持有的对象调用析构函数。

For example, if the vector uses an array as a backing store and currently contains 10 elements, then calling clear() will call the destructor of each object in the array, but the backing array will not be deallocated , so there is still sizeof(T) * 10 bytes allocated to the vector (at least).例如,如果vector使用一个数组作为backing store,当前包含10个元素,那么调用clear()会调用数组中每个对象的析构函数,但是backing数组不会被deallocated ,所以还是有sizeof(T) * 10个字节分配给向量(至少)。 size() will be 0, but size() returns the number of elements in the vector, not necessarily the size of the backing store. size()将为 0,但size()返回向量中的元素数,不一定是后备存储的大小。

As for your second question, anything you allocate with new you must deallocate with delete .至于您的第二个问题,您使用new分配的任何内容都必须使用delete解除分配。 You typically do not maintain a pointer to a vector for this reason.出于这个原因,您通常不会维护指向向量的指针。 There is rarely (if ever) a good reason to do this and you prevent the vector from being cleaned up when it leaves scope.很少有(如果有的话)这样做的充分理由,并且当向量离开作用域时,您会阻止它被清理。 However, calling clear() will still act the same way regardless of how it was allocated.然而,不管它是如何分配的,调用clear()仍然会以相同的方式运行。

if I use the clear() member function.如果我使用clear()成员函数。 Can I be sure that the memory was released?我能确定内存被释放了吗?

No, the clear() member function destroys every object contained in the vector, but it leaves the capacity of the vector unchanged.不, clear()成员函数会销毁向量中包含的每个对象,但它使向量的容量保持不变。 It affects the vector's size, but not the capacity.它影响向量的大小,但不影响容量。

If you want to change the capacity of a vector, you can use the clear-and-minimize idiom , ie, create a (temporary) empty vector and then swap both vectors.如果要更改向量的容量,可以使用clear-and-minimize idiom ,即创建一个(临时)空向量,然后交换两个向量。


You can easily see how each approach affects capacity.您可以轻松了解每种方法如何影响容量。 Consider the following function template that calls the clear() member function on the passed vector:考虑以下函数模板,它在传递的向量上调用clear()成员函数:

template<typename T>
auto clear(std::vector<T>& vec) {
   vec.clear();
   return vec.capacity();
}

Now, consider the function template empty_swap() that swaps the passed vector with an empty one:现在,考虑将传递的向量与空向量交换的函数模板empty_swap()

template<typename T>
auto empty_swap(std::vector<T>& vec) {
   std::vector<T>().swap(vec);
   return vec.capacity();
}

Both function templates return the capacity of the vector at the moment of returning, then:两个函数模板都返回返回时刻向量的容量,然后:

std::vector<double> v(1000), u(1000);
std::cout << clear(v) << '\n';
std::cout << empty_swap(u) << '\n';

outputs:输出:

1000
0

Move semantics allows for a straightforward way to release memory, by simply applying the assignment (=) operator from an empty rvalue:移动语义允许通过简单地从空右值应用 赋值 (=) 运算符来提供一种直接的方法来释放内存:

std::vector<uint32_t> vec(100, 0);
std::cout << vec.capacity(); // 100

vec = vector<uint32_t>();    // Same as "vector<uint32_t>().swap(vec)";    
std::cout << vec.capacity(); // 0

It is as much efficient as the "swap()"-based method described in other answers (indeed, both are conceptually doing the same thing).它与其他答案中描述的基于“swap()”的方法一样有效(实际上,两者在概念上都在做同样的事情)。 When it comes to readability, however, the assignment version makes a better job at expressing the programmer's intention while being more concise.然而,在可读性方面,作业版本在表达程序员意图方面做得更好,同时更简洁。

You can free memory used by vector by this way:您可以通过这种方式释放 vector 使用的内存:

//Removes all elements in vector
v.clear()

//Frees the memory which is not used by the vector
v.shrink_to_fit();

If you need to use the vector over and over again and your current code declares it repeatedly within your loop or on every function call, it is likely that you will run out of memory.如果您需要一遍又一遍地使用向量,并且您当前的代码在循环中或每次函数调用中重复声明它,则很可能会耗尽内存。 I suggest that you declare it outside, pass them as pointers in your functions and use:我建议你在外面声明它,在你的函数中将它们作为指针传递并使用:

my_arr.resize()

This way, you keep using the same memory sequence for your vectors instead of requesting for new sequences every time.这样,您可以继续为向量使用相同的内存序列,而不是每次都请求新序列。 Hope this helped.希望这有帮助。 Note: resizing it to different sizes may add random values.注意:将其调整为不同的大小可能会添加随机值。 Pass an integer such as 0 to initialise them, if required.如果需要,传递一个整数(例如 0)来初始化它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM