首页 文章

如何从向量初始化数组? (如何将指针强制转换为数组?)

提问于
浏览
0

我正在尝试从 std::vector 的数据构建 std::array . 我目前这样做了:

#include <vector>
#include <array>

int main(void)
{
    std::vector<int>    vec{{1, 2, 3, 4, 5}};
    std::array<int, 5>  arr{static_cast<int [5]>(vec.data())};

    (void)arr;
    return 0;
}

但是gcc不接受这个演员:

错误:从'int *'类型的static_cast无效到类型'int [5]'

我以为数组可以用作指针,为什么我们不能这样做?

编辑:这不是Copy std::vector into std::array的副本,因为我的问题是 initialization (构造) std::array ;不要复制到它 .

编辑:我这样做了:

#include <vector>
#include <array>

int main(void)
{
    std::vector<int>    vec{{1, 2, 3, 4, 5}};
    int                 *a(vec.data());
    std::array<int, 5>  arr{*reinterpret_cast<int (*)[5]>(&a)};

    (void)arr;
    return 0;
}

但阵列没有初始化...... gcc说:

error:必须使用大括号括起初始化程序初始化数组

4 回答

  • 2

    std::array 是聚合类型;它没有任何用户定义的构造函数 . 它的单个数据成员是一个数组,不能在函数或构造函数调用中传递;通过值传递的数组衰减到指向其第一个元素的指针,以及array passed by reference cannot be used to initialize an array data member .

    这意味着一个 array<T, N> 可以通过另一 array<T, N> 或高达在 {} -enclosed列表 N 类型的 T 值的文字序列仅初始化 .

    从C 17开始,您将能够使用库函数to_array将对数组的引用转换为 std::array

    std::array<int, 5>  arr{std::experimental::to_array(*reinterpret_cast<int (*)[5]>(&a))};
    

    正如您在Possible implementation部分中看到的,这是在内部分别初始化每个元素:

    return { {a[I]...} };
    
  • 0

    您可以使用递归模板来实现与您想要的类似的东西 . 诀窍是使用变量模板中的...运算符将参数列表构造到数组构造函数,该变量模板具有所需的向量元素索引作为其可变参数 . 在实现此目的的下面的实现中,然后在模板中完成数组本身的构造,并且您可以依赖返回值优化来确保不进行复制以将值获取到最终数组中 . 这实现了你从矢量初始化数组的既定目标,虽然它有点人为,并不一定是你真正想做的事情 .

    #include <vector>
    #include <array>
    #include <iostream>
    
    template<typename T, unsigned total_elem_count, unsigned remain_elem_count, unsigned... elements>
    struct init_array_from_vec_helper
    {   
        static std::array<T, total_elem_count> array_from_vec(const std::vector<T>& cont)
        {   
            return init_array_from_vec_helper<T, total_elem_count, remain_elem_count-1, remain_elem_count-1, elements...>::array_from_vec(cont);
        }   
    };  
    
    
    template<typename T, unsigned total_elem_count, unsigned... elements>
    struct init_array_from_vec_helper<T, total_elem_count, 0, elements...>
    {   
        static std::array<T, total_elem_count> array_from_vec(const std::vector<T>& cont)
        {   
            return std::array<T, total_elem_count>{cont[elements]...};
        }   
    };  
    
    template<typename T, unsigned total_elem_count>
    std::array<T, total_elem_count> init_array_from_vec(const std::vector<T>& vec)
    {   
        return init_array_from_vec_helper<int, total_elem_count, total_elem_count-1, total_elem_count-1>::array_from_vec(vec);
    }   
    
    int main(void)
    {   
        std::vector<int>    vec{{1, 2, 3, 4, 5}};
    
        std::array<int, 5> arr(init_array_from_vec<int, 5>(vec));
    
        (void)arr;
    
        for(int i : arr)
            std::cout << i << std::endl;
    
        return 0;
    }
    
  • 0

    "I thought an array could be used as a pointer so why cannot we do this cast?"

    您可以使用数组作为指针,因为它们是"decay" . 见"What is array decaying?"

    但事实恰恰相反 . (还有对不同大小的数组进行类型检查 . )

    虽然 static_cast 可用于反转某些隐式转换,但这只是't one of them. It'明确地excluded from the list

    5)如从NEW_TYPE到表达式的类型标准转换序列存在,不包括左值到右值,阵列到指针,函数到指针,空指针,空构件指针,函数指针,(从C 17)或布尔转换开始,static_cast可以执行隐式转换的反转 .

    所以这可能会让你想知道如何将指针转换为数组类型 . 你不能,因为"Arrays are second-class citizens in C (and thus in C++)." reinterpret_cast 也不会工作 .

    (如果您尝试使用像 (int [5])(vec.data()) 这样的C风格的演员表,您可能会获得更明确的消息 ISO C++ forbids casting to an array type 'int [5]' . )

    所以's just how the language implementation falls out. And here what you'正在尝试初始化一个 std::array ,其存在的理由只是wrap a C array

    此容器是一种聚合类型,其语义与包含C样式数组T [N]作为其唯一非静态数据成员的结构相同 .

    因此,当涉及到初始化表单时,它对于C数组来说并不是一样的 . 如果你手中有一个整数指针并想从该指针初始化一个 int arr[5] = ... ,那你也同样不走运 . 你必须复制它 .

    在这种情况下,可以用...完成

    Copy std::vector into std::array

  • 2

    来自cpp array参考:

    数组类是聚合类型,因此没有自定义构造函数 .

    您应该使用默认初始化构造它,然后将矢量内容复制到它 .

相关问题