当我直接构造一个向量作为参数与使用定义为变量的向量时,这是不同的,有人可以解释为什么吗?
#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 发出了更清晰的错误:
error C2100: you cannot dereference an operand of type 'std::ranges::dangling'