是否可以/建议返回一个范围?

2024-04-24

我正在使用范围库来帮助我的类中的文件管理器数据,如下所示:

class MyClass
{
public:
    MyClass(std::vector<int> v) : vec(v) {}

    std::vector<int> getEvens() const
    {
        auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
        return std::vector<int>(evens.begin(), evens.end());
    }

private:
    std::vector<int> vec;
};

在这种情况下,一个新的向量被构建在getEvents()功能。为了节省这种开销,我想知道是否可以/建议直接从函数返回范围?

class MyClass
{
public:
    using RangeReturnType = ???;

    MyClass(std::vector<int> v) : vec(v) {}

    RangeReturnType getEvens() const
    {
        auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
        // ...
        return evens;
    }

private:
    std::vector<int> vec;
};

如果可能的话,我是否需要考虑任何终生注意事项?

我也有兴趣知道是否可以/建议将范围作为参数传递,或将其存储为成员变量。或者范围库更适合在单个函数的范围内使用?


这是在op的评论部分提出的,但我想我会在答案部分回应:

Ranges 库看起来很有前途,但我对这个返回的汽车有点担心。

请记住,即使添加auto,C++是一种强类型语言。就你而言,既然你要回来evens,那么返回类型将与evens。 (从技术上讲,它将是evens, but evens无论如何都是一个值类型)

In fact, you probably really don't want to type out the return type manually: std::ranges::filter_view<std::ranges::ref_view<const std::vector<int>>, MyClass::getEvens() const::<decltype([](int i) {return ! (i % 2);})>> (141 characters)


  • 正如 @Caleth 在评论中提到的,事实上,这也不起作用evens是在函数内部定义的 lambda,即使两个不同的 lambda 基本相同,其类型也会不同,因此实际上无法在此处获取完整的返回类型。

虽然对于是否使用可能存在争议auto或在不同情况下不使用,但我相信大多数人都会使用auto这里。再加上你的evens被宣布为auto同样,输入类型只会降低这里的可读性。


那么,如果我想访问子集(例如偶数),我有什么选择?无论是否有 Ranges 库,我还应该考虑其他方法吗?

根据您访问返回数据的方式和数据类型,您可能会考虑返回std::vector<T*>.

views确实应该从头到尾看一遍。虽然你可以使用views::drop and views::take为了限制为单个元素,它还没有提供下标运算符。

计算上也会存在差异。vector需要预先计算,其中views是在迭代时计算的。所以当你这样做时:

for(auto i : myObject.getEven())
{
    std::cout << i;
}

在幕后,它基本上在做:

for(auto i : myObject.vec)
{
    if(!(i % 2)) std::cout << i;
}

取决于数据量和计算的复杂性,views可能会快很多,或者与vector方法。此外,您可以轻松地在同一范围内应用多个过滤器,而无需多次迭代数据。

最后,您可以随时存储view in a vector:

std::vector<int> vec2(evens.begin(), evens.end());

所以我的建议是,如果你有范围库, 然后你should use it.

If not, then vector<T>, vector<T*>, vector<index> depending on the size and copiability of T.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以/建议返回一个范围? 的相关文章