Tom*_*bel 13 c++ vector c++20 std-span
我知道这可能与问题重叠:什么是 \xe2\x80\x9cspan\xe2\x80\x9d 以及我何时应该使用它?,但我认为问题的这个特定部分的答案相当令人困惑。一方面,有这样的引用:
\n\n\n如果您有一个标准库容器(或 Boost 容器等),并且您知道它最适合您的代码,请不要使用它。它无意取代其中任何一个。
\n
但在同一个答案中,出现了这样的说法:
\n\n\n当您希望数据在内存中连续时,是将 const vector& 传递给函数的合理替代方案。再也不用被 C++ 大师骂了!
\n
那么我没有到达哪一部分呢?我什么时候会这样做:
\nvoid foo(const std::vector<int>& vec) {}\n
Run Code Online (Sandbox Code Playgroud)\n而这是什么时候呢?
\nvoid foo(std::span<int> sp) {}\n
Run Code Online (Sandbox Code Playgroud)\n还有,这会不会
\nvoid foo(const std::span<int> sp) {}\n
Run Code Online (Sandbox Code Playgroud)\n有什么意义吗?我认为不应该,因为 astd::span
只是 a struct
,包含指针和长度。但是,如果它不能阻止您更改std::vector
作为参数传递的值,那么它如何替换const std::vector<T>&
?
Gui*_*cot 13
相当于传递 astd::vector<int> const&
不是std::span<int> const
,而是std::span<int const>
。跨度本身是否为常量不会真正改变任何东西,但更多的常量无疑是一个很好的实践。
那么什么时候应该使用它呢?
我想说,这完全取决于函数的主体,您在示例中省略了函数的主体。
例如,我仍然会为此类函数传递一个向量:
std::vector<int> stored_vec;
void store(std::vector<int> vec) {
stored_vec = std::move(vec);
}
Run Code Online (Sandbox Code Playgroud)
这个函数确实存储了向量,所以它需要一个向量。这是另一个例子:
void needs_vector(std::vector<int> const&);
void foo(std::vector<int> const& vec) {
needs_vector(vec);
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我们需要一个向量。对于跨度,您必须创建一个新向量并因此进行分配。
对于这种函数,我会传递一个跨度:
auto array_sum(std::span<int const> const values) -> int {
auto total = int{0};
for (auto const v : values) {
total += v;
}
return total;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这个函数不需要向量。
即使您需要改变范围内的值,您仍然可以使用跨度:
void increment(std::span<int> const values) {
for (auto& v : values) {
++v;
}
}
Run Code Online (Sandbox Code Playgroud)
对于 getter 之类的东西,我也倾向于使用跨度,以免暴露对类成员的直接引用:
struct Bar {
auto get_vec() const -> std::span<int const> {
return vec;
}
private:
std::vector<int> vec;
};
Run Code Online (Sandbox Code Playgroud)