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

发布于 2024-08-05 12:36:18 字数 4317 浏览 3 评论 0原文

我对以下内容不太清楚。

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

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

I am unclear about the following.

First, this code compiles fine:

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

The following code is near identical:

#include <vector>

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

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

but it throws the extremely length error output I will include at the end. Why does the compiler treat these two programs so differently? It is definitely not intuitive.

Here is the compiler error that is thrown on my system that is using g++ to compile:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

相思碎 2024-08-12 12:36:18

错误: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< /code> 可以包含数组。
因此,一个简单的修复方法是:

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

error: ISO C++ forbids initialization
in array new
error: array must be
initialized with a brace-enclosed
initializer
error: invalid array
assignment
error: request for
member ‘~int [4]’ in ‘* __p’, which is
of non-class type ‘int [4]’

To understand one of the errors, imagine the following:

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

As opposed to:

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

int main()
{
    ints a;
    ints b = a;
}

Or even:

typedef struct{
    int x[4];
}  ints;

int main()
{
    ints a;
    ints b = a;
}

C/C++ arrays cannot be copied via the assignment operator, though structs containing arrays can be.
So an easy fix is to do:

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);
}
缱倦旧时光 2024-08-12 12:36:18

在幕后它正在做一个分配,并且没有为数组定义。

错误的相关部分

从这里实例化 /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:错误:无效的数组分配

Under the hood it's doing an assignment and that isn't defined for arrays.

The pertinent part of the error is

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

带上头具痛哭 2024-08-12 12:36:18

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

Try boost::array instead of plain arrays. It provides STL-compliant interface around fixed-size arrays, so it can be used inside STL containers. Plus, it implements boundary checking (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);
}
九公里浅绿 2024-08-12 12:36:18

自从我使用 C++ 以来已经有一段时间了,但我相信您遇到的核心问题是数组不具备与 std::vector<> 相处所需的语义。 。我手边没有 Stroustrup 的副本,否则我可以给你一个参考。

It's been a little while since I used C++, but I believe the core problem you're encountering is that arrays don't have the required semantics to get along well with a std::vector<>. I don't have my copy of Stroustrup handy, or I'd give you a reference.

暗地喜欢 2024-08-12 12:36:18

尝试使用 vectorvector 来代替。

Try using a vector of vector instead.

猫弦 2024-08-12 12:36:18

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

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

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

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

之所以不能,是因为上面代码片段中的 ab 根据以下公式衰减为指针类型右值: 4.2[conv.array] 中描述的数组到指针衰减的常用 C++ 规则。当然,如果不允许在非重载 operator= 的左侧使用右值。

The requirement for value type T for all STL containers, including std::vector<T>, is that T is Assignable - ISO C++03 23.1[lib.container.requirements]/4-5. Assignable is defined as follows:

Expression t = u, where t is of type T, and u is of type cv T, is valid, its return type is T&, and the post-condition is that t is equivalent to u.

Arrays do not fulfill this requirement, because you cannot write:

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

The reason why you cannot is because both a and b in the code snippet above decay to pointer-type rvalues according to the usual C++ rules for array-to-pointer decay described in 4.2[conv.array]. Naturally, an rvalue if not permitted on the left side of non-overloaded operator=.

抱猫软卧 2024-08-12 12:36:18

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

Arrays are not first class in C++; you cannot pass them as arguments to functions, for example (they decay to pointers, although you can pass pointers and references to arrays). Further, they do not have value semantics.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文