字符串向量并使用 C++20 范围进行变换

Kob*_*obi 1 c++ c++20

以下 C++20 范围基本语法有什么问题 (Ubuntu 20.04, gcc g++ (Ubuntu 10-20200411-0ubuntu1) 10.0.1 20200411 (实验) [master revision bb87d5cc77d:75961caccb7:f883c46b4877f637e0fa5025b4d6b5c9 040ec566]):

#include <iostream>
#include <vector>
#include <ranges>

[[nodiscard]]
auto f(const std::vector<std::string>& vec) {
   return vec | std::views::transform([] (const std::string &f){ 
      return f.size(); });
}

int main() {
    const auto v = f({"c", "dddddddd", "aaaa", "bb"});
    for(auto i : v)
        std::cout << i << ' ';
    std::cout << '\n';
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想获取一个字符串向量并将其转换为每个字符串的大小。

尝试使用 C++11 范围 for 循环进行迭代只会崩溃。在 gdb 中,我可以看到 std::ranges 视图指向无效内存。

使用与上面相同的结构处理非字符串效果很好。

bol*_*lov 5

你的编译器没有任何问题。您的代码具有未定义的行为。视图是惰性计算的,并且要求当您访问它们时底层容器仍然处于活动状态。你所拥有的类似于悬空引用。

{"c", "dddddddd", "aaaa", "bb"}在这里,您创建一个临时向量,该向量在包含调用的完整表达式的末尾处终止f(也称为直到行尾;),因此当您访问 时它就终止vfor(auto i : v)f.size();在 for range 循环之前,不会调用 lambda 中的。但此时正如我所说,临时向量及其所有字符串元素不再存在。

为了帮助减轻这种错误,您可以禁止使用临时变量调用 f:

auto f(std::vector<std::string>&& vec) = delete;
Run Code Online (Sandbox Code Playgroud)