关于在C ++中将数组存储在std :: vector中的问题

时间:2009-09-23 19:16:27

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

我不清楚以下情况。

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

#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]’

7 个答案:

答案 0 :(得分:11)

  

错误:ISO C ++禁止初始化   在数组中新的错误:数组必须是   用括号括起来初始化   初始化程序
错误:数组无效   分配
错误:请求   '* __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 ++数组,但包含数组的struct可以是。
所以很容易解决:

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);
}

答案 1 :(得分:6)

在幕后,它正在进行一项任务,而且没有为数组定义。

错误的相关部分是

从这里实例化/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&lt; _Tp,_Alloc&gt; :: push_back(const _Tp&amp;)实例化[with _Tp = int [4],_ Alloc = std ::分配器]'test2.cpp:9:从这里实例化/usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits /vector.tcc:312:错误:数组分配无效

答案 2 :(得分:6)

尝试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);
}

答案 3 :(得分:2)

自从我使用C ++以来已经有一段时间了,但我相信你遇到的核心问题是数组没有必要的语义来与std::vector<>相处得很好。我没有方便的Stroustrup副本,或者我会给你一个参考。

答案 4 :(得分:2)

请尝试使用vector代替vector

答案 5 :(得分:1)

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

  

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

数组不符合此要求,因为您无法写:

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

你不能这样做的原因是因为上面代码片段中的ab根据4.2中描述的数组到指针衰减的常用C ++规则衰减到指针式rvalues [ conv.array。当然,如果不允许在非重载operator=的左侧允许rvalue。

答案 6 :(得分:-1)

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