直接作为范围参数构造的 C++ 向量不能用作期望器

问题描述 投票:0回答:1

当我直接构造一个向量作为参数与使用定义为变量的向量时,这是不同的,有人可以解释为什么吗?

#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;
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
c++ std-ranges
1个回答
0
投票

您的函数

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'
© www.soinside.com 2019 - 2024. All rights reserved.