C++ 解除分配 std::vector 对象的“正确”方式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3054567/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:55:04  来源:igfitidea点击:

"Right" way to deallocate an std::vector object

c++stlvectormemory-management

提问by Jacob

The first solution is:

第一个解决方案是:

std::vector<int> *vec = new std::vector<int>;
assert(vec != NULL);
// ...
delete vec;

An alternativeis:

另一种选择是:

std::vector<int> v;
//...
vec.clear();
vec.swap(std::vector<int>(vec));

The second solution's a bit of a trick --- what's the "right" way to do it?

第二种解决方案有点小技巧——“正确”的方法是什么?

Update:

更新:

I'm aware that the destructor will be called once it's off the stack, I was curious about other methods.

我知道析构函数一旦离开堆栈就会被调用,我对其他方法很好奇。

回答by JaredPar

The simplest and most reliable way to deallocate a vector is to declare it on the stack and simply do nothing.

释放向量的最简单和最可靠的方法是在堆栈上声明它并且什么都不做。

void Foo() {
  std::vector<int> v;
  ...
}

C++ guarantees that the destructor of vwill be called when the method executes. The destructor of std::vectorwill ensure any memory it allocated is freed. As long as the Ttype of the vector<T>has proper C++ deallocation semantics all will be well.

C++ 保证v在方法执行时会调用的析构函数。的析构函数std::vector将确保释放它分配的任何内存。只要 的T类型vector<T>具有适当的 C++ 释放语义,一切都会好起来的。

回答by Mike Seymour

The simplest way to deallocate all the storage in a vector, without destroying the vector object itself, is

在不破坏向量对象本身的情况下,释放向量中所有存储空间的最简单方法是

vec = std::vector<int>();

Your second variant will have the same effect, but it jumps through more hoops on the way. The "copy and swap" trick deallocates any extra capacity in the vector, and can be useful if it contains some data you want to keep. If there's no data, then there's no need for copying or swapping.

您的第二个变体将具有相同的效果,但它会在途中跳过更多的箍。“复制和交换”技巧会释放向量中的任何额外容量,如果它包含一些您想要保留的数据,它会很有用。如果没有数据,则无需复制或交换。

回答by deft_code

std::vector<int> vi;
/*push lots of stuff into the vector*/

// clean it up in C++03
// no need to clear() first
std::vector<int>().swap(vi);

// clean it up in C++0x
// not a one liner, but much more idiomatic
vi.clear();
vi.shrink_to_fit();

回答by Sam

I agree with Mike Seymour try this then you will notice that the last is working fine

我同意 Mike Seymour 试试这个然后你会注意到最后一个工作正常

const int big_size = 10000;
vector<double> v( big_size );
cout << "Before clearing, the capacity of the vector is "
  << v.capacity() << " and its size is " << v.size();
v.clear();
cout << "\nAfter clearing, the capacity of the vector is "
  << v.capacity() << " and its size is " << v.size();
vector<double>().swap( v );

cout << "\nAfter swapping, the capacity of the vector is "
  << v.capacity() << " and its size is " << v.size();

vector<double> v1( big_size );
v1 = vector<double>();
cout << "\n After vector<double>();, the capacity of the vector is "
  << v1.capacity() << " and its size is " << v1.size();

回答by Patrick

Don't use memory allocation functions unless you really need to. If your class needs a vector, always, just ad the std::vector member directly. No need to do memory allocation here.

除非确实需要,否则不要使用内存分配函数。如果你的类需要一个向量,总是直接添加 std::vector 成员。这里不需要做内存分配。

In the cases where you need the dynamic vector, allocating and deleting it like in your first example is 100% correct.

在需要动态向量的情况下,像在第一个示例中那样分配和删除它是 100% 正确的。

In the second example, the call to std::swap is strictly spoken not needed, because the clear method will clear the vector, making it empty. One possible problem is that there is no guarantee that the vector will actually free the memory, giving it back to the operating system (or to the run time). The vector might keep the allocated memory just in case you will fill the vector right after clearing it. The call to std::swap may be a trick to 'force' the vector to free its internal data, but there is no guarantee that this will actually happen.

在第二个示例中,严格来说不需要调用 std::swap,因为 clear 方法将清除向量,使其为空。一个可能的问题是,无法保证向量实际上会释放内存,将其返还给操作系统(或运行时)。向量可能会保留分配的内存,以防您在清除向量后立即填充向量。对 std::swap 的调用可能是一种“强制”向量释放其内部数据的技巧,但不能保证这会实际发生。

回答by Winston Ewert

My guess here is that you have a vector which temporarily contains a large amount of data. Once the vector has been cleared, it will still take up all of this memory. You want to release this memory after you are done with it, but you the function/object you are working with has not finished.

我的猜测是您有一个临时包含大量数据的向量。一旦向量被清除,它仍然会占用所有这些内存。您想在完成后释放此内存,但您正在使用的函数/对象尚未完成。

Solutions in decreasing order of desirability:

按需求降序排列的解决方案:

  1. Rework the code so that the vector using code is in it's own block/function/object so that it will be destroyed naturally
  2. Use the swap trick, this way you don't have to worry about making sure that the vector is deallocated in all circumstances. It's lifetime will be tied to the object/function you are in.
  3. new/delete the vector. This will free up a little bit more memory then the previous method but is also harder to make sure no memory is leaked.
  1. 重新编写代码,使使用代码的向量位于其自己的块/函数/对象中,以便自然销毁
  2. 使用交换技巧,这样您就不必担心确保在所有情况下都释放向量。它的生命周期将与您所在的对象/函数相关联。
  3. 新建/删除向量。这将比之前的方法释放更多的内存,但也更难确保没有内存泄漏。

The only technical difference between swapping and deleting is the base vector itself is not destroyed. This is a small overhead and is not worth worrying about (as long as you do eventually destroy the vector)

交换和删除之间唯一的技术区别是基向量本身没有被破坏。这是一个很小的开销,不值得担心(只要你最终破坏了向量)

The larger consideration is which makes it easier to write correct code, and I believe swap wins over deleting there, but is worse then moving the vector somewhere else.

更大的考虑是它可以更容易地编写正确的代码,我相信交换胜过在那里删除,但比将向量移到其他地方更糟糕。

回答by Cubbi

This is not a valid comparison because the examples are dealing with different kinds of objects: dynamic duration and local duration. You can call the destructor OR use the swap trick (aka shrink_to_fit) with either one. The rightway depends on whether you need the vector object to persist or not.

这不是一个有效的比较,因为这些示例处理不同类型的对象:动态持续时间和局部持续时间。您可以调用析构函数或使用交换技巧(又名shrink_to_fit)与任一。在正确的方式取决于你是否需要矢量对象坚持与否。

For example, you may need it to persist if there are references or pointers to itthat must remain valid, in which case shrinking is the only way, regardless of how it was allocated.

例如,如果存在必须保持有效的引用或指向它的指针,您可能需要它持久化,在这种情况下,收缩是唯一的方法,无论它是如何分配的。

回答by Mark Ransom

I'm not sure why your second example uses a copy constructor for the temporary rather than a default constructor. That would save you the .clear()line of code.

我不确定为什么您的第二个示例使用临时构造函数而不是默认构造函数的复制构造函数。这将为您节省.clear()代码行。

You could make this generic for any object, even if it's not a container. I'm assuming here that std::swap is specialized to call vector::swap.

即使它不是容器,您也可以将其设置为任何对象的通用对象。我在这里假设 std::swap 专门用于调用 vector::swap。

template<typename T>
void ResetToDefault(T & value)
{
    std::swap(T(), value);
}

std::vector<int> vec;  
//...  
ResetToDefault(vec);

回答by Martin Beckett

Delete deallocates the memory, the memory is then free for the next object but the vector has gone.

删除会释放内存,然后内存可用于下一个对象,但向量已消失。

The 2nd trick frees any excess memory but leaves the vector intact, but empty.

第二个技巧释放任何多余的内存,但保持向量完好无损,但为空。

回答by Ben313

Although both appear to work, I see no reason not to just call delete on the pointer. The vector should have a destructor that is called that will handle everything else.

尽管两者似乎都有效,但我认为没有理由不直接在指针上调用 delete。该向量应该有一个被调用的析构函数,它将处理其他所有事情。