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

vector of strings and transform with C++20 ranges

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

#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;
}

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

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

使用与上述相同的结构处理非字符串工作正常。

似乎是 10.0.1 的错误。 以 Pete 为例并在 10.0.1 上尝试重现该问题。 (无限循环) 。 https://godbolt.org/z/PqdceV 10.1 上的完全相同的代码产生了所需的行为。我想我现在需要坚持使用编译器资源管理器来学习范围。

你的编译器没有问题。您的代码具有未定义的行为。视图是惰性评估的,并且要求在您访问它们时底层容器仍然存在。你所拥有的类似于悬空引用。

{"c", "dddddddd", "aaaa", "bb"} 这里你创建了一个 临时 向量,它在包含调用 f (a.k.a直到行尾 ;),所以当你在 for(auto i : v) 中访问 v 时它就死了。在你的范围循环之前,你的 lambda 中的 f.size(); 不会被调用。但在这一点上,正如我所说,你的临时向量及其所有字符串元素都不存在了。

为了帮助缓解此类错误,您可以禁止使用临时对象调用 f:

auto f(std::vector<std::string>&& vec) = delete;