![](/img/trans.png)
[英]Why does std::when_any use std::tuple rather than std::vector as its result type?
[英]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::array
、 std::vector
、C 风格的数组)。 当然,这也可以通过传递 C 风格 arrays 来完成 - std::span
只是 C 风格 arrays 的包装,增加了一些安全性和便利性。
两者之间的另一个区别:为了修改 function 中拥有vector
的大小(例如,通过std::vector::assign
或std::vector::clear
),您宁愿传递std::vector&
而不是一个std::span
,因为span
不提供这些功能。
您可以修改std::span
的内容,但不能更改其大小。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.