如何在不丢失现有数据的情况下调整 std::vector 的大小?

Posted

技术标签:

【中文标题】如何在不丢失现有数据的情况下调整 std::vector 的大小?【英文标题】:How to resize an std::vector without loosing the existing data? 【发布时间】:2016-08-26 23:32:04 【问题描述】:

我正在实现一种算法,该算法需要我在循环的每次迭代中从向量中删除和添加相同的元素。

例子:

迭代 1 : |1 2 3 4| (4号)

迭代 2 : |1 3| 2 4(大小为 2,元素 '2' 和 '4' 仍在内存中,但未计入向量的大小)

迭代 3:|1 2 3| 4(尺寸为 3,元素 '4' 仍然存在)

基本上,出于性能原因,我希望能够在不影响向量的情况下更改 size() 函数返回的值。

我知道我可以使用向量之外的另一个变量来跟踪它的大小,但我想知道它是否可以直接在 std::vector 容器内部。

感谢您的帮助。

【问题讨论】:

改变你的设计:谈论迭代器,而不是容器和大小。然后,您可以按照您想要的任何方式对数据进行混洗、置换和分区,但是您可以将 迭代器 分配给算法的有趣范围。 当您使用擦除“缩小”向量时,容量不会改变。这决定了何时需要重新分配向量。 @NathanOliver 这里没有关于容量和重新分配的内容。 【参考方案1】:

您想要的与vector 的工作方式在逻辑上不一致。 size 返回 vectorT 类型的对象的数量。通过减小该尺寸,任何从末端切掉的物体都会被破坏。当您增加大小时,您正在添加新对象

最好围绕 vector 构建一个具有您想要的行为的类型。

【讨论】:

【参考方案2】:

你不能这样做。

减少size() 报告的值的唯一方法是调整大小。当调整大小减小大小时,就程序而言,新大小之外的元素不再存在。任何访问它们的方式(或在您的情况下重新访问它们)都会产生未定义的行为。

如果您想跟踪正在使用的数组的元素数量(例如,您正在使用具有五个元素的向量的两个元素),则创建一个额外的变量来跟踪它。为了说明(希望)显而易见,该变量需要与向量的大小保持一致(例如,避免跟踪在具有五个元素的向量中使用了十个元素)。

如果要将变量与向量一起保留,请将两个成员都设为 struct/class 类型。该类可以提供成员函数或操作来管理向量和“正在使用”的元素数量,以确保一致性。

【讨论】:

感谢您的回答,我想我得自己跟踪尺寸了【参考方案3】:

我不知道,也许用has-a 代替is-a

template <typename T> class subvector 
protected:
  std::vector<T> owner_;
  std::size_t    begin_;
  std::size_t    end_;
public:
  subvector(std::vector<T>& owner, size_t from, size_t to) :
    owner_(owner), begin_(from), end_(to)
  
     // do some range checks
  

  size_t size() const 
    // range check before return
    // either throw (fast-fail) *or* 
    //   adjust the out-of-range ends (lenient but maybe unsafe)
    return end_-begin_+1;
  
  // implement as many of the std::vector methods/operators
  // you are likely to need in your code by delegation
  // to the owner_.
  // Stay minimal, whenever you use something you don't have, 
  // the compiler will tell you.
; 

【讨论】:

感谢您的回答。我清楚地理解了您的代码 sn-p,但我无法理解您所说的“使用 has-a 而不是 is-a”是什么意思。你能澄清一下吗? @CpCd0y 它是对多态性继承的描述,如果你公开继承,你正在做一个is-a,如果你使用一些东西,你正在创建一个has-a的类。如果我是对的,这个术语很可能来自“Effective C++”这本书。 @CpCd0y is-a 通过继承派生 - 使用方法覆盖来自定义行为。 has-a 由组合派生 - 包裹一个对象,将所有行为委托给包裹的对象,在委托之前自定义您想要的那些。 @Ben - 作为参考,“Effective C++”可能对于不知情的人来说是一个很好的起点。就个人而言,我还没有读过它(这就是为什么“可能”),但这些模式在 OOP 世界中很常见,无论语言如何 "Is-a" 和 "has-a" 不是 OO 模式。它们是实体之间关系的描述(根据上下文,可能是对象、类等)。 “is-a”关系描述了涉及类型专业化的特定关系(例如,拉布拉多犬是狗)。所有权和组成都是“拥有”关系的两种类型(例如,一个人有一个家,或者一个人有一条腿)。在 C++ 中,“is-a”通常使用公共继承来实现,而“has-a”关系可以通过多种方式实现(私有继承、包含/成员资格、包含指针等)。

以上是关于如何在不丢失现有数据的情况下调整 std::vector 的大小?的主要内容,如果未能解决你的问题,请参考以下文章

在不丢失 Exif 数据的情况下调整图像大小?

如何在不丢失表格视图单元格的情况下将现有集合视图添加到表格视图

如何在不丢失原始参与者的情况下将现有呼叫升级到会议?

如何在不覆盖现有样式的情况下向 WPF 自定义控件添加触发器?

如何保存 html 画布,然后在不丢失形状的情况下重新加载它?

无法在不覆盖的情况下将 R 数据框附加到现有 Excel 中