Namespaces
Variants
Views
Actions

Array declaration

From cppreference.com
< cpp‎ | language
Revision as of 18:59, 31 May 2013 by P12bot (Talk | contribs)

 
 
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements
Jump statements
Functions
function declaration
lambda function declaration
function template
inline specifier
exception specifications (deprecated)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
decltype specifier (C++11)
Specifiers
cv specifiers
storage duration specifiers
constexpr specifier (C++11)
auto specifier (C++11)
alignas specifier (C++11)
Initialization
Literals
Expressions
alternative representations
Utilities
Types
typedef declaration
type alias declaration (C++11)
attributes (C++11)
Casts
implicit conversions
const_cast conversion
static_cast conversion
dynamic_cast conversion
reinterpret_cast conversion
C-style and functional cast
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 

Declares an object of array type.

Contents

Syntax

An array declaration is any simple declaration whose declarator has the form

noptr-declarator [ constexpr(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
constexpr - a constant expression of integral type which evaluates to a value greater than zero

A declaration of the form T a[N];, declares a as an array object that consists of N contiguously allocated objects of type T. The elements of an array are numbered 0...N-1, and may be accessed with the member access operator [], as in a[0] ... a[N-1].

Arrays can be constructed from any fundamental type (except void), pointers, pointers to members, classes, enumerations, or from other arrays (in which case the array is said to be multi-dimensional). There are no arrays of references, arrays of functions, or arrays of incomplete types.

Assignment

Objects of array type cannot be modified: even though they are lvalues (e.g. an address of array can be taken), they cannot appear on the left hand side of an assignment operator:

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

Array to pointer decay

There is an implicit conversion from lvalues and rvalues of array type to rvalues of pointer type: it constructs a pointer to the first element of an array. This conversion is used whenever arrays appear in context where arrays are not expected, but pointers are:

#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); // OK: function takes an array by reference
//  g(p); // Error
 
    for(int n: a)              // OK: 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); // OK: begin/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); // OK: function takes a pointer
    f(p); // OK: function takes a pointer
 
    std::cout << *a << '\n' // prints the first element
              << *p << '\n' // same
              << *(a+1) << ' ' << a[1] << '\n' // prints the second
              << *(p+1) << ' ' << p[1] << '\n';
}


Multidimensional arrays

When the element type of an array is another array, it is said that the array is multidimensional:

// array of 2 arrays of 3 ints each
int a[2][3] = {{1,2,3},  // can be viewed as a 2x3 matrix
               {4,5,6}}; // with row-major layout

Note that when array-to-pointer conversion is applied, a multidimensional array is converted to a pointer to its first element, e.g., pointer to the first row:

int a[2][3]; // 2x3 matrix
int (*p1)[3] = a; // pointer to the first 3-element row
int b[3][3][3]; // 3x3x3 cube
int (*p2)[3][3] = a; // pointer to the first 3x3 plane

Arrays of unknown bound

If constexpr is omitted in the declaration of an array, the type declared is "array of unknown bound of T", which is a kind of incomplete type, except when used in a declaration with an aggregate initializer:

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"

Array rvalues

An array rvalue expression may be formed by accessing an array member of a class rvalue or by using an identity template to construct an array temporary directly:

#include <iostream>
#include <type_traits>
 
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 arrary
    f(X().i); // OK, binds to rvalue
//  f(x.i);   // Error: cannot bind to lvalue
 
    f(identity<int[][3]>{{1,2,3},{4,5,6}}); // OK, binds to rvalue
}

Output:

24
24
24