【问题标题】:From vectors of objects return one object as reference从对象向量返回一个对象作为参考
【发布时间】:2021-02-28 07:46:31
【问题描述】:
#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'

类型

get_next_model2

为什么会出现这个错误?

我正在使用

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

我需要

  1. Models的向量中找到next_model
  2. next_model.next_event_time 设置为0

在我作为副本返回之前Model get_next_model(std::vector&lt;Model&gt; &amp;models)。 但是使用它我正在修改副本的.next_eventtime`。

【问题讨论】:

  • @PatrickRoberts 很抱歉,谢谢您可以将此评论作为对the question i deletedplease 的答复吗?
  • 这只是为了您的利益,您不需要取消删除问题。反正我真的没准备好写详细的解释。

标签: c++ c++20


【解决方案1】:

接受任意范围的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; }
    );
}

Live Demo

【讨论】:

  • 如果models 为空,从min_element() 取消引用返回值会给出未定义的行为。最好在取消引用之前检查一下。
【解决方案2】:

您不能从const vector&lt;Model&gt; 返回非常量模型引用。使您的返回类型为const Model&amp; 或者简单地在get_next_model2 中声明models 参数而不使用const 关键字。

Model& get_next_model2(std::vector<Model> &models)

或者:

const Model& get_next_model2(const std::vector<Model> &models)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-04
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    • 2013-05-28
    相关资源
    最近更新 更多