当我直接构造一个向量作为参数与使用定义为变量的向量时,情况有所不同,有人可以解释为什么吗?
#include <cstdlib>
#include <iostream>
#include <ostream>
#include <ranges>
#include <vector>
using namespace std;
template <std::ranges::range R>
std::ranges::borrowed_iterator_t<R> random_elt(R&& r) {
auto it = r.begin();
for (size_t i = 0; i < ::rand() % std::ranges::size(r); i++) {
it++;
}
return it;
}
int main() {
std::vector<int> v{1, 2, 3};
// This is fine.
cout << *random_elt(v) << endl;
// Surely this should be the same?
cout << *random_elt(std::vector<int>({1, 2, 3})) << endl;
}
错误:
$ g++ -o main main.cpp -std=gnu++23
main.cpp: In function ‘int main()’:
main.cpp:24:13: error: no match for ‘operator*’ (operand type is ‘std::ranges::borrowed_iterator_t<std::vector<int> >’)
24 | cout << *random_elt(std::vector<int>({1, 2, 3})) << endl;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
您的函数模板
random_elt
通过引用接受范围并返回一个迭代器。第一种情况是可以的,因为范围是基于的,
std::vector v
其生命周期超过了输出的使用量random_elt
。但在第二种情况下,参数
std::vector<int>({1, 2, 3})
是临时的。因此,您返回的迭代器random_elt
变为悬空的operator*
,并且当范围的生存期结束时,您尝试用 取消引用它。您从 gcc 发布的错有点不直观,但在这种情况下 MSVC 发出了一个更清晰的错误:
带有 MSVC 错误的现场演示