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

问题描述 投票:0回答:7

我不清楚以下内容。

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

#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 g++ stdvector
7个回答
11
投票

错误: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++ 数组无法通过赋值运算符进行复制,但

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

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<_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: 错误:无效数组作业


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

2
投票

自从我使用 C++ 以来已经有一段时间了,但我相信您遇到的核心问题是数组不具备与

std::vector<>
相处良好所需的语义。 我手边没有 Stroustrup 的副本,否则我会给你一个参考。


2
投票

尝试使用

vector
vector
来代替。


1
投票

所有 STL 容器(包括

T
)对值类型
std::vector<T>
的要求是
T
Assignable
- ISO C++03 23.1[lib.container.requirements]/4-5。
Assignable
定义如下:

表达式

t = u
(其中
t
的类型为
T
u
的类型为 cv
T
)有效,其返回类型为
T&
,后置条件为
 t
相当于
u

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

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

之所以不能,是因为上面代码片段中的

a
b
都根据 4.2[conv.array] 中描述的数组到指针衰减的常用 C++ 规则衰减为指针类型右值。当然,如果不允许在非重载的左侧使用右值
operator=


-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.