Array declaration
数组声明
声明数组类型的对象。
句法
数组声明是指其报关员有表格。
noptr-declarator expr(optional) attr(optional) | (1) | |
---|
noptr-declarator | - | any valid declarator, but if it begins with *, &, or &&, it has to be surrounded by parentheses. |
---|---|---|
attr(C++11) | - | optional list of attributes |
expr | - | an integral constant expression (until C++14)a converted constant expression of type std::size_t (since C++14), which evaluates to a value greater than zero |
表格的声明T a[N];
,声明a
的数组对象。N
连续分配的类型对象T
数组的元素被编号。0, …, N - 1
,并且可以使用下标算子。[],如a[0]
...,a[N - 1]
...
数组可以从任意基本类型%28除外void
%29,指针,,,对成员的指示,,,班,,,枚举,或者来自其他数组%28,在这种情况下,该数组被称为多维%29。没有引用数组、函数数组或抽象类类型数组。
应用简历-资格对于数组类型%28,通过类型类型为%28或模板类型,操纵%29将限定符应用于元素类型,但任何元素为cv限定类型的数组类型都被认为具有相同的cv-限定。
二次
// a and b have the same const-qualified type "array of 5 const char"
typedef const char CC;
CC a[5] = {};
typedef char CA[5];
const CA b = {};
二次
当与新。[]---表达,数组的大小可能为零;这样的数组没有元素:
二次
int* p = new int[0]; // accessing p[0] or *p is undefined
delete[] p; // cleanup still required
二次
赋值
数组类型的对象不能作为一个整体进行修改:即使它们是lvalue%28等。数组的地址可以取为%29,它们不能出现在赋值运算符的左侧:
二次
int a[3] = {1, 2, 3}, b[3] = {4, 5, 6};
int (*p)[3] = &a; // okay: address of a can be taken
a = b; // error: a is an array
struct { int c[3]; } s1, s2 = {3, 4, 5};
s1 = s2; // okay: implicity-defined copy assignment operator
// can assign data members of array type
二次
数组对指针衰减
有一个隐式转换从数组类型的lvalue和rvalue到指针类型的rvalue:它构造指向数组的第一个元素的指针。每当数组出现在不需要数组的上下文中时,都会使用这种转换,但是指针是:
二次
#include <iostream>
#include <numeric>
#include <iterator>
void g(int (&a)[3])
{
std::cout << a[0] << '\n';
}
void f(int* p)
{
std::cout << *p << '\n';
}
int main()
{
int a[3] = {1, 2, 3};
int* p = a;
std::cout << sizeof a << '\n' // prints size of array
<< sizeof p << '\n'; // prints size of a pointer
// where arrays are acceptable, but pointers aren't, only arrays may be used
g(a // okay: function takes an array by reference
// g(p // error
for(int n: a) // okay: arrays can be used in range-for loops
std::cout << n << ' '; // prints elements of the array
// for(int n: p) // error
// std::cout << n << ' ';
std::iota(std::begin(a), std::end(a), 7 // okay: begin and end take arrays
// std::iota(std::begin(p), std::end(p), 7 // error
// where pointers are acceptable, but arrays aren't, both may be used:
f(a // okay: function takes a pointer
f(p // okay: function takes a pointer
std::cout << *a << '\n' // prints the first element
<< *p << '\n' // same
<< *(a + 1) << ' ' << a[1] << '\n' // prints the second element
<< *(p + 1) << ' ' << p[1] << '\n'; // same
}
二次
多维阵列
当数组的元素类型是另一个数组时,就会说该数组是多维的:
二次
// array of 2 arrays of 3 int each
int a[2][3] = {{1, 2, 3}, // can be viewed as a 2 × 3 matrix
{4, 5, 6}}; // with row-major layout
二次
注意,当应用数组到指针衰减时,多维数组被转换为指向其第一个元素%28e的指针。指向其第一行或其第一个平面%29:数组到指针衰减的指针只应用一次。
二次
int a[2]; // array of 2 int
int* p1 = a; // a decays to a pointer to the first element of a
int b[2][3]; // array of 2 arrays of 3 int
// int** p2 = b; // error: b does not decay to int**
int (*p2)[3] = b; // b decays to a pointer to the first 3-element row of b
int c[2][3][4]; // array of 2 arrays of 3 arrays of 4 int
// int*** p3 = c; // error: c does not decay to int***
int (*p3)[3][4] = c; // c decays to a pointer to the first 3 × 4-element plane of c
二次
未知界数组
如果在数组的声明中省略Exr,则声明的类型是“T的未知界数组”,这是一种不完全类型,除非在声明中使用聚合初始化器*
二次
extern int x[]; // the type of x is "array of unknown bound of int"
int a[] = {1, 2, 3}; // the type of a is "array of 3 int"
二次
由于数组元素不能具有不完全类型,因此多维数组不能在第一个维度中具有未知的绑定:
二次
extern int a[][2]; // okay: array of unknown bound of arrays of 2 int
extern int b[2][]; // error: array has incomplete element type
二次
可以形成对未知绑定数组的引用和指针,但不能从数组和已知绑定数组中初始化或分配指针。注意,在C编程语言中,指向未知界数组的指针与指向已知界数组的指针兼容,因此在两个方向上都是可转换和可分配的。
二次
extern int a1[];
int (&r1)[] = a1; // okay
int (*p1)[] = &a1; // okay
int (*q)[2] = &a1; // error (but okay in C)
int a2[] = {1, 2, 3};
int (&r2)[] = a2; // error
int (*p2)[] = &a2; // error (but okay in C)
二次
指向未知绑定数组的指针不能参与指针算法控件的左边不能使用。下标算子,但可以取消引用。中不能使用指针和对未知绑定数组的引用。功能参数%28,直到C++14%29。
数组r值
虽然数组不能按值从函数返回,也不能成为大多数强制转换表达式的目标,但数组prvalue可以通过使用类型别名来构造数组临时使用支撑-初始化功能铸造...
Like class prvalues, array prvalues convert to xvalues by temporary materialization when evaluated. | (since C++17) |
---|
列阵x值可以通过访问类rvalue的数组成员或使用std::move
或者返回rvalue引用的另一个强制转换或函数调用。
二次
#include <iostream>
#include <type_traits>
#include <utility>
void f(int (&&x)[2][3])
{
std::cout << sizeof x << '\n';
}
struct X
{
int i[2][3];
} x;
template<typename T> using identity = T;
int main()
{
std::cout << sizeof X().i << '\n'; // size of the array
f(X().i // okay: binds to xvalue
// f(x.i // error: cannot bind to lvalue
int a[2][3];
f(std::move(a) // okay: binds to xvalue
using arr_t = int[2][3];
f(arr_t{} // okay: binds to prvalue
f(identity<int[][3]>{{1, 2, 3}, {4, 5, 6}} // okay: binds to prvalue
}
二次
产出:
二次
24
24
24
24
24
二次
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。