【问题标题】:Question about storing array in a std::vector in C++关于在 C++ 中将数组存储在 std::vector 中的问题
【发布时间】:2025-11-25 08:10:02
【问题描述】:

我不清楚以下内容。

首先,这段代码编译得很好:

#include <vector>

typedef struct{
    int x1,x2,x3,x4;
}  ints;

typedef std::vector<ints> vec;

int main(){
    vec v;
    ints a = {0,1,2,3};
    v.push_back(a);
}

以下代码几乎相同:

#include <vector>

typedef std::vector<int[4]> vec;

int main(){
    vec v;
    int a[4] = {0,1,2,3};
    v.push_back(a);
}

但它会引发我将在最后包含的极长错误输出。为什么编译器对这两个程序的处理如此不同?这绝对不直观。

这是在我使用 g++ 编译的系统上引发的编译器错误:

[mattg@pigott Test]$ g++ test2.cpp -o test2
In file included from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/i586-redhat-linux/bits/c++allocator.h:34,
                 from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/allocator.h:48,
                 from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/vector:62,
                 from test2.cpp:2:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/ext/new_allocator.h: In member function ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = int [4]]’:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/stl_vector.h:737:   instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = int [4], _Alloc = std::allocator<int [4]>]’
test2.cpp:9:   instantiated from here
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/ext/new_allocator.h:105: error: ISO C++ forbids initialization in array new
In file included from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/vector:69,
                 from test2.cpp:2:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = int [4], _Alloc = std::allocator<int [4]>]’:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/stl_vector.h:741:   instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = int [4], _Alloc = std::allocator<int [4]>]’
test2.cpp:9:   instantiated from here
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/vector.tcc:306: error: array must be initialized with a brace-enclosed initializer
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/stl_vector.h:741:   instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = int [4], _Alloc = std::allocator<int [4]>]’
test2.cpp:9:   instantiated from here
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/vector.tcc:312: error: invalid array assignment
In file included from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/i586-redhat-linux/bits/c++allocator.h:34,
                 from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/allocator.h:48,
                 from /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/vector:62,
                 from test2.cpp:2:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/ext/new_allocator.h: In member function ‘void __gnu_cxx::new_allocator<_Tp>::destroy(_Tp*) [with _Tp = int [4]]’:
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/vector.tcc:353:   instantiated from ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = int [4], _Alloc = std::allocator<int [4]>]’
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/stl_vector.h:741:   instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = int [4], _Alloc = std::allocator<int [4]>]’
test2.cpp:9:   instantiated from here
/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/ext/new_allocator.h:115: error: request for member ‘~int [4]’ in ‘* __p’, which is of non-class type ‘int [4]’

【问题讨论】:

    标签: c++ gcc compiler-construction g++ stdvector


    【解决方案1】:

    错误:ISO C++ 禁止初始化 在数组中 new
    错误:数组必须是 用大括号括起来的初始化 初始化程序
    错误:无效数组 分配
    错误:请求 ‘* __p’中的成员‘~int [4]’,即 非类类型“int [4]”

    要了解其中一个错误,请想象以下情况:

    void main() {
        int a[4] = {0,1,2,3};
        int b[4] = a;
    }
    

    相对于:

    typedef struct{
        int x1,x2,x3,x4;
    }  ints;
    
    int main()
    {
        ints a;
        ints b = a;
    }
    

    甚至:

    typedef struct{
        int x[4];
    }  ints;
    
    int main()
    {
        ints a;
        ints b = a;
    }
    

    C/C++ 数组不能通过赋值操作符复制,但包含数组的 structs 可以。
    所以一个简单的解决方法是:

    typedef struct{
            int x[4];
    }  ints;
    
    typedef std::vector<ints> vec;
    
    int main(){
            vec v;
            ints a = { {0,1,2,3} };
            v.push_back(a);
    }
    

    【讨论】:

      【解决方案2】:

      在后台,它正在执行一项分配,并且未为数组定义。

      错误的相关部分是

      从这里实例化 /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/vector.tcc:306 :错误:数组必须用大括号括起来的初始化程序进行初始化 /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include /c++/4.4.1/bits/stl_vector.h:741: 实例化自 'void std::vector<_tp _alloc>::push_back(const _Tp&) [with _Tp = int [4], _Alloc = std::allocator ]' test2.cpp:9: 从这里实例化 /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/ vector.tcc:312:错误:无效的数组分配

      【讨论】:

      • 这些模板错误的工作方式是编译器尝试实例化给定类型的模板——然后编译生成的代码。当它遇到错误时,它会尝试让您了解它发现问题的代码与您编写的代码之间的关系,并且它假设您知道模板的源代码以便您可以理解错误。您必须忽略所有“实例化自”cmets 才能找到问题
      • 我听说 C++0x(也就是 C++1x,按照这个速度)可能会在这些东西上出现更友好的错误。
      • @Brain 可能不会。改进的错误取决于已从 C++0x 中删除的概念。
      【解决方案3】:

      尝试boost::array 而不是普通数组。它围绕固定大小的数组提供符合 STL 的接口,因此可以在 STL 容器中使用。此外,它还实现了边界检查 (boost::array::at)。

      #include <boost/array.hpp>
      #include <vector>
      
      typedef std::vector< boost::array<int, 4> > vec;
      int main(){
          vec v;
          boost::array<int, 4> va = {0,1,2,3};
          v.push_back(va);
      }
      

      【讨论】:

      • 或者,如果在您的实现中可用,则使用 std::tr1::array(与 Boost 相同,但符合 ISO 标准)。
      【解决方案4】:

      我使用 C++ 已经有一段时间了,但我相信您遇到的核心问题是数组不具备与std::vector&lt;&gt; 相处所需的语义。我手边没有我的 Stroustrup 副本,或者我会给你一个参考。

      【讨论】:

        【解决方案5】:

        尝试改用vectorvector

        【讨论】:

        • 我认为使用数组向量可能是合法的愿望。 (我自己可能过度使用向量的向量,因为我不知道 boost::array 之类的东西。)
        【解决方案6】:

        对于所有 STL 容器(包括 std::vector&lt;T&gt;),值类型 T 的要求是 TAssignable - ISO C++03 23.1[lib.container.requirements]/4-5。 Assignable 定义如下:

        表达式t = u,其中t 的类型为Tu 的类型为cv T,有效,其返回类型为T&amp;,并且后置条件是t 等价于u

        数组不满足这个要求,因为你不能写:

        int a[2], b[2];
        a = b;
        

        之所以不能,是因为上面代码 sn-p 中的 ab 根据 4.2[conv.大批]。当然,如果不允许在非重载 operator= 的左侧使用右值。

        【讨论】:

          【解决方案7】:

          数组不是 C++ 中的第一类;例如,您不能将它们作为参数传递给函数(它们衰减为指针,尽管您可以传递指针和引用 to 数组)。此外,它们没有值语义。

          【讨论】: