Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;带有std::span的Ranges-v3:从函数返回范围视图时中间对象的所有权_C++_Range V3 - Fatal编程技术网

C++ C++;带有std::span的Ranges-v3:从函数返回范围视图时中间对象的所有权

C++ C++;带有std::span的Ranges-v3:从函数返回范围视图时中间对象的所有权,c++,range-v3,C++,Range V3,我对Eric Niebler的ranges-V3库(到目前为止我都很喜欢!)是一个完全的初学者,但是在从函数返回范围时遇到了一些问题。我想我发现了这个问题,但是对于ranges API在本例中的默认行为感到有点惊讶。由于我没有在其他地方找到任何关于这个问题的参考资料,而且花费了我相当多的时间,所以我把我的问题写得有点广泛,希望这能对将来的其他人有所帮助 问题出现在下面的最小示例中,这会导致未定义的行为 #include <iostream> #include "range/v3/al

我对Eric Niebler的ranges-V3库(到目前为止我都很喜欢!)是一个完全的初学者,但是在从函数返回范围时遇到了一些问题。我想我发现了这个问题,但是对于ranges API在本例中的默认行为感到有点惊讶。由于我没有在其他地方找到任何关于这个问题的参考资料,而且花费了我相当多的时间,所以我把我的问题写得有点广泛,希望这能对将来的其他人有所帮助

问题出现在下面的最小示例中,这会导致未定义的行为

#include <iostream>
#include "range/v3/all.hpp"
#include "nonstd_span.h"

auto from_span() {  
    // make this static for the array to persist after the fct returns
    static int my_array[10] = { 1,2,3,4,5,6,7,8,9,10 };
    auto my_span = nonstd::span<int>(my_array, 10); 
    return ranges::views::all(my_span);
}

int main() {
    std::cout << from_span() << std::endl;
    return 0;
}
  • 还可以为外部拥有的跨度构建一个小型内存/生命周期管理系统

  • 在我看来,这些解决方案都不是特别优雅的,它们会为在这种情况下使用范围视图增加大量样板代码和复杂性(缩短语法和不必考虑生命周期正是我试图实现的目标)

    我觉得我可能遗漏了一些东西,应该有一个更优雅的解决方案,其中范围视图拥有/复制它所包含的轻型对象(如跨度或其他视图)


    span
    不是任务的正确工具吗?它似乎是为像这样的用例创建的?

    这个范围库可能不知道
    nonsd::span
    是一个
    视图。您需要通过专门化
    ranges::enable_view
    来判断它。如果没有这一点,范围库会认为它类似于一个向量,当您将它的左值传递给
    views::all
    时,会返回一个引用本地
    span
    对象的视图,而不是
    span
    的副本


    在最近的过去,range-v3会使用一种启发式方法(正确地)猜测
    span
    是一个视图,而您的代码就可以正常工作了。它由C++委员会更改了每个请求,而不喜欢启发式。公平地说,它有时会猜错。

    运行第一个代码段时会发生什么?我不确定那里是否有UB。当我使用
    ranges::span
    时,它似乎对我来说很有用。在我的系统上,它似乎大部分时间都在工作,即打印
    [1,2,3,4,5,6,7,8910]
    。有时
    分段错误
    ,有时空列表
    []
    。我是如何意识到有一个问题的,那就是在我使用的实际代码中,
    returnranges::any_视图(ranges::views::all(my_span))以强制转换为通用类型。在这种情况下,它通常会打印出非常随机的数字,大多数时候我认为错误和任何视图有关。@cigien谢谢,这很有趣,我尝试了gcc10.1的godbolt(我认为它完全支持C++20),但无法使std::span正常工作。我需要一点时间来追踪我的系统的差异。还不确定,我在系统上给出的非常简单的示例总是需要一些时间来强制执行奇怪的行为。在这种特殊情况下,您可以只返回
    范围::视图::全部(我的数组)
    ,而不使用
    span
    。谢谢Eric,这充分解释并解决了这个问题。当我写这个问题时,我没有意识到
    ranges::span
    ,一旦我切换到这个问题,整个问题就不会发生。同时,对图书馆的巨大感谢,我的C++代码将开始看起来非常不同。
    auto from_span() {
        using namespace ranges;
        static int my_array[10] = { 1,2,3,4,5,6,7,8,9,10 }; 
        auto span_ptr = std::make_unique<nonstd::span<int>>(my_array, 10);  
        return std::make_tuple(views::all(*span_ptr), std::move(span_ptr));
    }
    
    
    int main() {
        auto [rng, my_span_ptr] = from_span();  
        std::cout << rng << std::endl;
        return 0;
    }