【问题标题】:Is assigning empty std::vector same as swaping for an empty std::vector?分配空的 std::vector 是否与交换空的 std::vector 相同?
【发布时间】:2022-01-24 16:35:25
【问题描述】:

C++ delete vector, objects, free memory 指出,为了在清除 std::vector 后释放分配的堆内存,可以这样做:

vector<int>().swap(myVector);

这是有道理的,但我想知道以下是否不会达到同样的效果。谁能告诉我是否有区别?

myVector = vector<int>();

【问题讨论】:

  • 第二个选项可以调用移动赋值,唯一利用移动赋值的方法就是在语句结束时释放所有现有内存。撇开合法性不谈,如果一个人需要进行交换以实现任务应该做的事情,那将是一种耻辱。
  • @user1095108 我同意。我认为没有绝对的万无一失的方法可以使向量的容量变为零。我认为可以实现始终使用最小大小的缓冲区。您必须依靠空向量甚至没有尝试分配的实现常识。
  • 唯一万无一失的方法是让向量超出范围。当您显然不打算重用它的容量时,为什么要保留它呢?所以放下它,并在您再次需要时创建一个新的(保证为空)向量。
  • @BoP 它可能是一个成员变量

标签: c++ memory vector swap


【解决方案1】:

这些替代品之间没有显着差异。

但是,我推荐第三种选择,因为它对读者来说更明显:

myVector.clear();
myVector.shrink_to_fit();

【讨论】:

  • 但这并不能保证释放内存,不是吗?
  • @matthias_buehlmann 不比其他替代品更多,不。
  • 据我了解,其他替代方案应该保证内存的释放,因为旧对象已被破坏。没有?
  • @matthias_buehlmann 该对象在所有这些替代方案中都没有被破坏。虽然交换可以保证旧的分配被释放,但它不能保证向量的默认构造函数不会进行另一个分配。
  • @MarkRansom 如果你愿意依赖这样的假设(如果你这样做了,我不会怪你),那么为什么不也依赖shrink_to_fit 在空向量上的假设很可能取消分配任何重要的分配?
【解决方案2】:

谁能告诉我有区别吗?

如果是myVector = vector&lt;int&gt;();

旧内存不一定被释放(释放)。

但如果是vector&lt;int&gt;().swap(myVector);

旧的内存释放将会发生。

【讨论】:

  • 谢谢。您能否详细说明为什么在一种情况下会释放内存而在另一种情况下不会释放内存?
  • @matthias_buehlmann 该标准并未强制要求减小向量的大小会减少分配。保持原始分配可能更有效,尤其是在向量再次增长的情况下。
【解决方案3】:

根据标准,为(非std::array)容器is not allowed to invoke the move constructor or assignment operators of T unless the allocator for that container does not propagate on container move-assignment 的右值赋值(即:移动赋值)。这意味着此类分配器的vectors 的唯一有效实现是销毁当前分配并采用右值中的分配。 std::allocator 确实在容器移动分配上传播,因此此类容器的任何移动分配都将强制采用右值的内容。

这是否意味着myVector = vector&lt;int&gt;(); 保证采用空分配?不必要。 检测右值容器为空的实现完全有效,销毁它自己的元素,但保留它的内部分配以供以后使用。

相比之下,vector::swap 的实现做同样的事情是不可行的。迭代器/指针/引用保存要求确保一个容器中对象的迭代器/指针/引用映射到另一个容器中的对象(只要分配器通过容器交换上的传播允许这一点)。这意味着两个对象内的分配实际上必须交换,即使其中一个没有分配。赋值没有这样的迭代器保存要求。

话虽如此,假设实现将是病态的并积极尝试避免您尝试删除容器的分配并不是一个好主意。同样,对shrink_to_fit 的调用不能保证容量会发生变化......但是没有的实现将是一个非常愚蠢的实现。

因此有人可能会争辩说,最好的代码应该是清楚地解释正在发生的事情的代码。 swap 是一个成语,你必须让别人解释你为什么在这样的prvalue上使用它。 clear() 后跟 shrink_to_fit 可以从文档中清楚地说明您在做什么;无需解释。

所以也许考虑这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 2020-09-22
    • 1970-01-01
    • 2012-03-07
    • 2012-06-30
    相关资源
    最近更新 更多