繁体   English   中英

为什么我应该将 std::span 而不是 std::vector& 传递给 function?

[英]Why in particular should I rather pass a std::span than a std::vector& to a function?

我知道这可能与什么是“跨度”以及何时应该使用“跨度”这个问题重叠? ,但我认为问题的这个特定部分的答案非常令人困惑。 一方面,有这样的引用:

如果您有一个您知道适合您的代码的标准库容器(或 Boost 容器等),请不要使用它。 它并不打算取代其中任何一个。

但在同一个答案中,出现了以下语句:

当您希望您的数据在 memory 中是连续的时,这是将 const vector& 传递给函数的合理替代方法。 再也不用被高大上的C++大师骂了!

那么我没有到达这里的哪一部分? 我什么时候会这样做:

void foo(const std::vector<int>& vec) {}

什么时候?

void foo(std::span<int> sp) {}

还有,这会

void foo(const std::span<int> sp) {}

有什么意义吗? 我认为它不应该,因为std::span只是一个struct ,包含一个指针和长度。 但是,如果它不阻止您更改作为参数传递的std::vector的值,它如何替换const std::vector<T>&

传递std::vector<int> const&的等价物不是std::span<int> const ,而是std::span<int const> 跨度本身是否为 const 并不会真正改变任何东西,但更多的 const 肯定是好的做法。

那么什么时候应该使用呢?

我会说它完全取决于您在示例中省略的 function 的主体。

例如,我仍然会为这种函数传递一个向量:

std::vector<int> stored_vec;

void store(std::vector<int> vec) {
    stored_vec = std::move(vec);
}

这个 function 确实存储了向量,所以它需要一个向量。 这是另一个例子:

void needs_vector(std::vector<int> const&);

void foo(std::vector<int> const& vec) {
    needs_vector(vec);
}

如您所见,我们需要一个向量。 使用跨度,您必须创建一个新向量并因此进行分配。


对于这种功能,我会传递一个跨度:

auto array_sum(std::span<int const> const values) -> int {
    auto total = int{0};

    for (auto const v : values) {
        total += v;
    }

    return total;
}

如您所见,这个 function 不需要向量。

即使您需要改变范围内的值,您仍然可以使用 span:

void increment(std::span<int> const values) {
    for (auto& v : values) {
        ++v;
    }
}

对于 getter 之类的东西,我也倾向于使用跨度,以免暴露对 class 成员的直接引用:

struct Bar {
    auto get_vec() const -> std::span<int const> {
        return vec;
    }

private:
    std::vector<int> vec;
};

关于传递&std::vector和传递std::span之间的区别,我可以想到两件重要的事情:

  • std::span允许您仅传递您希望 function 查看或修改的数据,而不是整个向量(并且您不必传递开始索引和结束索引)。 我发现这对于保持代码干净是非常必要的。 毕竟,您为什么要让 function 访问超出其需要的数据?
  • std::span可以从多种类型的容器中获取数据(例如std::arraystd::vector 、C 风格的数组)。

当然,这也可以通过传递 C 风格 arrays 来完成 - std::span只是 C 风格 arrays 的包装,增加了一些安全性和便利性。

两者之间的另一个区别:为了修改 function 中拥有vector的大小(例如,通过std::vector::assignstd::vector::clear ),您宁愿传递std::vector&而不是一个std::span ,因为span不提供这些功能。

您可以修改std::span的内容,但不能更改其大小。

暂无
暂无

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

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