【问题标题】:How do I construct a subrange of vector by reference?如何通过引用构造向量的子范围?
【发布时间】:2019-10-05 00:30:22
【问题描述】:

我目前正在使用std::vector 的范围构造函数来创建给定子范围的另一个向量。

std::vector<int> myVect { 1, 2, 3, 4 };

std::vector<int> subrangeVector(myVect.begin(), myVect.begin() + 2);

但是,这会导致 myVect 的范围值被复制并占用额外的内存。当使用有限的内存和/或非常大的元素类型时,这是不可取的。

如何通过引用构造另一个向量的子范围?

我的目标的简化解释如下:

void fun(std::vector<int> & v) { v.at(0) = 1; }

int main()
{
    std::vector<int> myVect { 1, 2, 3, 4 };

    std::size_t upperLimit = 5;
    std::vector<int> subrangeVector = subrangeView(myVect, upperLimit);

    fun(subrangeVector);  // so myVect.at(0) == 1

    return 0;
}

这将在许多使用std::vector 作为参数的不同函数中实现。我不想像here 讨论的那样传递迭代器。假设我无法控制函数fun

【问题讨论】:

  • 为什么要这样做?这就是迭代器的初衷。任何你想传递新的“子范围参考向量”的地方,你都可以通过两个迭代器来完成同样的事情。或者如果你想把它当作一个向量,你可以用你所有的向量函数为迭代器创建一个包装类。
  • 你不能 - std::vector 总是拥有它的参数。但是,C++20 中的 std::spanstd::view::counted 提供标准的非拥有视图。
  • @Brian 您应该将其写为答案,在使用std::reference_wrapper 进行几次实验后,我确信并看到当前标准无法以简单的方式实现。至少可以在循环中逐项获取引用。
  • @paddycakes “我的问题与我的目标无关,因此与帖子无关。” 在评论中询问您的用例是有效的,并且被认为是相关的.您的评论听起来不友好,请在这里保持文明。
  • @paddycakes 因为我不想传递迭代器 是的,我假设是这样。您可能希望节省有关避免复制的效率。虽然似乎没有直接访问迭代器的方法。

标签: c++ slice stdvector reference-type


【解决方案1】:

C++ 向量是一种“拥有”其内存的类型 - 它不能是另一个向量数据的“引用类型”。

相反,您可能会发现span 很有用:跨度是表示内存中连续数据的类 - 就像向量一样;但是 - 它一个“引用类型”,它拥有 - 正是你想要的。它的行为就像一个向量 w.r.t.迭代,operator[],等等。

在你的情况下,你会写:

std::vector<int> myVect { 1, 2, 3, 4 };
auto subrange { std::span{myVect}.subspan(0, 2); }

然后按照您对向量的计划使用子范围。

PS:这是 C++20 代码,因为 C++17 还没有跨度;如果您使用的是早期 C++ 版本,请使用指南支持库中的 gsl::span(例如来自 here)。

【讨论】:

  • “它不能是另一个向量数据的“引用类型””——好吧,如果它是 std::vectorstd::reference_wrapper 的那种类型,可以。跨度>
  • @JesperJuhl:1. 你在扯皮。 2. 数据仍然是引用包装器,而不是引用对象。
  • 我知道。但这似乎与提及有关。有时reference_wrapper 确实是您想要使用的,而 OP 问题对我来说似乎是一种潜在的情况。
  • @JesperJuhl 至少我没有找到通过std::reference_wrapper 实现这一点的方法。
猜你喜欢
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多