Array dalam C ++


Kami melanjutkan seri "C ++, menggali lebih dalam". Tujuan dari seri ini adalah untuk memberi tahu Anda sebanyak mungkin tentang berbagai fitur bahasa, mungkin sangat istimewa. Ini adalah artikel keempat dalam seri, tiga yang pertama tentang kelebihan muatan di C ++ ada di sini , di sini dan di sini .

Artikel ini tentang array. Array dapat dikaitkan dengan lapisan paling kuno dari C ++, mereka berasal dari versi pertama C. Namun demikian, array termasuk dalam sistem tipe berorientasi objek dari C ++, meskipun dengan beberapa peringatan. Penting bagi programmer untuk mengetahui fitur-fitur ini untuk menghindari kemungkinan kesalahan. Artikel ini juga mengeksplorasi warisan C lainnya - tipe sepele dan variabel tidak diinisialisasi. Beberapa inovasi C ++ 11 memengaruhi pekerjaan dengan array, semua fitur baru ini juga dijelaskan secara rinci. Jadi, mari kita coba menceritakan segalanya tentang array.



Daftar Isi


Daftar Isi

  1.
    1.1.
    1.2.
    1.3.
    1.4.
  2.
    2.1.
    2.2.
  3.
    3.1.
    3.2.
      3.2.1
      3.2.2
      3.2.3
  4.
    4.1.
    4.2.
  5.
  6.
    6.1.
    6.2.
    6.3.
  7.
  8.
  




1. Ketentuan Umum


Array adalah tipe agregat yang paling sederhana. Ia memodelkan serangkaian elemen serupa yang tersusun dalam satu baris dalam segmen memori yang berkelanjutan. Array dalam satu bentuk atau yang lain didukung oleh hampir semua bahasa pemrograman, dan tidak mengherankan bahwa mereka muncul di versi pertama C dan kemudian menjadi bagian dari C ++.



1.1. Deklarasi susunan


Jika Tbeberapa jenis, Nkonstanta atau ekspresi dievaluasi pada waktu kompilasi, maka instruksi


T a[N];

a « N T» (array of N elements of the type T). N std::size_t, , , . sizeof(T) , , , N*sizeof(T) . . T[N], . , , , , .


(regular arrays), , «» C++ .

:


const int N = 8;
constexpr int Square(int n) { return n * n; }

int a1[1];
int a2[N];
int a3['Q'];
int a4[Square(2)];

:


int n;

int b1[0];   //  
int b2[n];   //      
int b3["Q"]; //     size_t

, 0 N-1. :


int a[4];
a[0] = 42;
int t = a[3];

, .


, .


int a[4], b[8];

. typedef:


typedef int I4[4];

(C++11) using:


using I4 = int[4];

:


I4 a, b;

,


int a[4], b[4];


1.2.


sizeof .


sizeof , .


_countof() ( MSVS <cstdlib>) , . ++17 std::size(), ( , ).


int a[4];
std::cout << sizeof(a) << ' ' << std::size(a) << '\n';

: 16 4


C++11 ( ) std::begin() std::end(). std::begin() , std::end() past-the-last . ( : std::cbegin(), std::cend().) for.


int a[4]{ 4, 3, 2, 1 };

for (auto t : a)
{
    std::cout << t << ' ';
}

:


std::sort(std::begin(a), std::end(a));


1.3.


, , , . , , . (, .) . (. 6) .



1.4.


, void.


.


int u, v;
int &rr[2] = { u, v }; // 

.


int * const rr[2] = { &u, &v };

( 3.2.)


C++11 std::reference_wrapper<>. , . , - get(). .


int u = 42, v = 5;
std::reference_wrapper<int> rr[2] = { u, v };
std::cout << rr[0] << ' ' << rr[1] << '\n'; // : 42 5
++rr[0];
rr[1].get() = 125;                          // get() 
std::cout << u << ' ' << v << '\n';         // : 43 125

.


int ff[2](double); // 

.


int (*ff[2])(double);

std::reference_wrapper<> , — , &. — std::function<>, .


auto.


auto x[2] = {1, 2}   // 

const , .


using I4 = int[4];
const I4 ci; //  ,   const int ci[4];


2.


, C++.



2.1.


, , «». (decay, array-to-pointer decay). (Decay .) , . sizeof, & ( ) . sizeof 1.2, 4. decltype , .


, . ( C) :


const int N = 100;
int a[N];
for (int *d = a, *end = d + N; d < end; ++d)
{
    *d = rand();
}

, .


.


void Foo(int a[4]);
void Foo(int a[]);
void Foo(int *a);

— . (, ).


.


// file 1
int A[4];

// file 2
extern int A[];

.


auto .


int a[4];
auto da = a; //  da   int*



template<typename T>
void Foo(T t);

, .


. ( C .) .


class B {/* ... */};
class D : public B {/* ... */};
void Foo(B[], int size); //     B

.


D d[4];
Foo(d, _countof(d));

sizeof(B) < sizeof(D), Foo() d ( , ) , , Foo() . , , .



2.2.


( ) , «». , :


using I4 = int[4];
I4 a;
I4 b = a; // 
I4 b2;
b2 = a; // 

.


I4 Foo(); // 

//, ( ) .


struct X 
{ 
    int A[4]; 
};

, .


X Foo();
X x;
X x2 = x;
X x3;
x3 = Foo();


3.


.



3.1.


++. , — . , . , . , ++, . , , , , , , . : , , , , .


, - . . , . , - , .


: (), , , , . , . .


, , .


++11 , ( <type_traits>). , . std::is_trivial<>::value true, T false .



3.2.



3.2.1.


, . , , . , , .


C :


int a[4] = { 1, 2, 3, 4 };

++11 (uniform initialization) :


int a[4]{ 1, 2, 3, 4 };

=, , , , .


, .


int a[] { 1, 2, 3, 4 };

, . , (, , ), . , , .


int a[4]{};

.


const int a[4] = { 3, 2, 1 };

, .


.


const char str[] = "meow";
const wchar_t wstr[] = L"meow";

, .


3.2.2.


++11 , . : .


class X
{
    int a[4]{ 1, 2, 3, 4 };
    int b[2];
// ...
public:
    X(int u, int v) : b{ u, v } 
    {}
// ...
};

, .


, , , .


class X
{
    static int A[];
// ...
};

int X::A[] = { 1, 2, 3, 4 };


3.2.3.


, , , (, , constexpr). , , — . :


T a[] = {x1 /*, ... */};



T a[]{x1 /*, ... */};



T t = x1;

. .


.


class Int
{
    int m_Value;
public:
    Int(int v) : m_Value(v) {}
// ...
};
// ...
int x, y;
// ...
Int rr[] = { x, y };

Int explicit, .


Int rr[] = { Int(x), Int(y) };

. .



4.



4.1.




T a[N];

:


T(*pa)[N] = &a;

&. T(*)[N].


, N T.


— ( , , ), . , «» . .


int a[4];
int(*pa)[4] = &a; // OK
int(*p2)[2] = &a; // ,   

, .


* .


(*pa)[3] = 42;

.


using I4 = int[4];
I4 a{ 1, 2, 3, 4 };
I4 *pa = &a;

auto, .


int a[4];
auto pa = &a; //  pa   int(*)[4]

, .



4.2.




T a[N];

:


T(&ra)[N] = a;

, . T(&)[N].


.


T(*pa)[N] = &a;
T(&ra)[N] = *pa;

, «» . .


int a[4];
int(&ra)[4] = a; // OK
int(&r2)[2] = a; // ,   

, .


ra[3] = 0;

, .




void Foo(T(&a)[N]);

T[N], .


.


using I4 = int[4];
I4 a{ 1, 2, 3, 4 };
I4 &ra = a;

auto, .


int a[4];
auto &ra = a; //  ra   int(&)[4]

& auto, , ra int*.




template<typename T>
void Foo(T& t);

, .


.


template<typename T, std::size_t N>
void Foo(T(&a)[N]);

T N ( ). , . _countof() std::size(), std::begin() std::end(), for . 5 .



5.


C++ , a[N, M] , « », a[N][M].


T , N M , ,


T a[N][M];

a , N , M T. . a[i][j], i 0 N-1, j 0 M-1, . , . N , M . T[N][M].


a[i] M T. , .


T *dai = a[i];
T(*pai)[M] = &a[i];
T(&rai)[M] = a[i];

. , .


T a[N][M];
T(*da)[M] = a;

, :


void Foo(T a[N][M]);
void Foo(T a[][M]);
void Foo(T(*a)[M]);

, .


.


using I4 = int[4];
I4 b[2];

,


int b[2][4];

:


int b[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};

, {}. .


int b[][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}}; // 
int b[][] = {{1, 2, 3, 4}, {5, 6, 7, 8}};  // 

:


T a[N][M];
T(*pa)[N][M] = &a;

. .


template<typename T, std::size_t N, std::size_t M>
void Print2dArray(T(&a)[N][M])
{
    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < M; ++j)
        {
            std::cout << a[i][j] << ' ';
        }
        std::cout << '\n';
    }
}
// ...
int b[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
Print2dArray(b);

:


1 2 3 4
5 6 7 8

.


T mtx[N][M];

N , M , mtx[i][j] i- j- , mtx[i] M, i- . , . , .



6.


C++ « ». , ( ). . C++ .



6.1.


T , n , ,


T *pa = new T[n];

. n std::size_t, . , , n*sizeof(T), . pa .


T , , .


C++11 .


int *pa = new int[n]{1, 2, 3, 4};

, ( , n ). , , . , , .


new[] . , , T , . - , , , . std::bad_alloc.


delete[], , new[].


delete[] pa;

, , , ( ), .


pa, new[], , ( «») , . for.



6.2.


std::unique_ptr<> (. [Josuttis]). , [] -> delete[] . :


int n = 100; 
std::unique_ptr<int[]> aptr(new int[n]);
for (int i = 0; i < n; ++i)
{
    aptr[i] = i; 
}

: , , for. std::unique_ptr<> , std::vector<>. std::shared_ptr<> .



6.3.


, new T[n][m], n m , . , , . M , , :


T(*pa)[M] = new T[n][M];

new[] . pa[i][j], pa[i] M T.


.


using I4 = int[4];
I4 *pa = new I4[n];

[] , , . .


// 2D interface to a buffer
template<typename T>
class MatrixView 
{
    T * const m_Buff;
    int const m_RowCount;
    int const m_ColCount;
public:
    MatrixView(T* buff, int rowCount, int colCount)
        : m_Buff(buff)
        , m_RowCount(rowCount)
        , m_ColCount(colCount)
    {}
    T *operator[](int rowInd) const
    {
        return m_Buff + rowInd * m_ColCount;
    }
};
// buffer owner
template<typename T>
class DynBuffer 
{
    T* const m_Buff;
protected:
    T* Buff() const { return m_Buff; };
    DynBuffer(int length) : m_Buff(new T[length]{}) {}
    ~DynBuffer() { delete[] m_Buff; }
    DynBuffer(const DynBuffer&) = delete;
    DynBuffer& operator=(const DynBuffer&) = delete;
};

template<typename T>
class MatrixSimple 
    : DynBuffer<T>, public MatrixView<T>
{
    using Buff = DynBuffer<T>;
    using View = MatrixView<T>;
public:
    MatrixSimple(int rowCount, int colCount)
        : Buff(rowCount * colCount)
        , View(Buff::Buff(), rowCount, colCount)
    {}
};

:


MatrixSimple<int> mtx(3, 3);
mtx[1][2] = 42; //  ,  

proxy-, , RowProxy, . , , , - begin(), end(), etc. .



7.


, «». T[]. .


//  
template <typename T>
class U
{
public:
    const char* Tag() const { return "base"; }
};

//    
template <typename T>
class U<T*>
{
public:
    const char* Tag() const { return "pointer"; }
};

//    
template <typename T>
class U<T[]>
{
public:
    const char* Tag() const { return "array"; }
};

U<int> u1;
U<int*> u2;
U<int[]> u3;

std::cout << u1.Tag() << ' ' << u2.Tag() << ' ' << u3.Tag();

: base pointer array


std::unique_ptr<>, , . 6.2.



8.


( ), .


std::array<>. ( C++11, . [Josuttis].) , : . , . :


std::array<int, 4> a{1, 2, 3, 4};

.


for (int i = 0; i < a.size(); ++i)
{
    std::cout << a[i] << ' ';
}
for (auto it = a.begin(); it != a.end(); ++it)
{
    std::cout << *it << ' ';
}
for (auto t : a)
{
    std::cout << t << ' ';
}

std::vector<>. , ( №1), - .


std::valarray<>. .




[Josuttis]
Josattis, Nikolai M. C ++ Perpustakaan Standar: Panduan Referensi, edisi kedua: Per. dari bahasa Inggris - M.: LLC “Saya. Williams, 2014.




All Articles