首页 > 解决方案 > 从对象向量返回一个对象作为参考

问题描述

#include <iostream>
#include <vector>
#include <random>
#include <ranges>
#include <algorithm>
#include <chrono>
#include <functional>


namespace ranges = std::ranges;

struct Model
{
    double next_event_time;
};

double timeit(int repeats, int items, std::function<void(int)> func)
{
    auto begin = std::chrono::steady_clock::now();
    for (auto i = 0; i < repeats; i++)
        func(items);
    auto end = std::chrono::steady_clock::now();
    auto dur = (end - begin);

    auto total_time = std::chrono::duration_cast<std::chrono::microseconds>(dur);

    return total_time.count() / repeats;
}

std::vector<Model> generate_examples(int number)
{

    std::default_random_engine generator;

    std::uniform_real_distribution<double> distribution(0.0, 1.0);

    std::vector<Model> models;

    for (auto i = 0; i < number; i++)
    {
        models.push_back(Model{.next_event_time = distribution(generator)});
    }

    return models;
}

Model& get_next_model(std::vector<Model> &models)
{
    ranges::sort(models, ranges::less{}, [](const Model &x) { return x.next_event_time; });

    return models[0];
}

Model& get_next_model2(const std::vector<Model> &models)
{
    // Error here 
    return ranges::min(models, ranges::less{}, [](const Model &x) { return x.next_event_time; });
}

void timeOne(int items)
{
    std::vector<Model> models = generate_examples(items);

    get_next_model(models);
}

void timeTwo(int items)
{
    auto models = generate_examples(items);
    get_next_model2(models);
}

int main()
{
    const std::string MS_UNIT = "[ms]";
    int items = 1000;
    int repeats = 10000;

    //std::cout << timeit(repeats, items, timeOne) << MS_UNIT << std::endl;
    std::cout << timeit(repeats, items, timeTwo) << MS_UNIT << std::endl;
    return 0;
}

如果我编译上面的代码,我得到

无法将“Model&”类型的非常量左值引用绑定到“std::ranges::range_value_t<const std::vector&>”类型的右值

get_next_model2

为什么我会收到这个错误?

我在用

  1. g++10.2
  2. 运行使用g++ -std=c++20 file.cpp

我需要

  1. 从s 的next_model向量中查找Model
  2. 将其设置next_model.next_event_time0

在我作为副本返回之前Model get_next_model(std::vector<Model> &models)。但是使用它我正在修改.next_event副本的时间。

标签: c++c++20

解决方案


的重载std::ranges::min接受按值返回的任意范围。因为它返回一个临时值,所以不能将非常量左值引用绑定到它的返回值。即使可以,该引用也会在get_next_model2返回后立即悬空。

改为使用std::ranges::min_elementmin_element将迭代器返回到范围内的最小值。请注意,如果您想从中返回非常量引用,get_next_model2则需要接受对您的非常量引用std::vector,因为const向量的元素都是它们本身const

Model& get_next_model2(std::vector<Model> &models)
{
    return *ranges::min_element(
        models,
        ranges::less{},
        [](const Model &x) { return x.next_event_time; }
    );
}

现场演示


推荐阅读