我们将继续“深入探索C ++”系列。本系列文章的目的是尽可能多地告诉您该语言的各种功能,可能很特殊。这是本系列的第四篇文章,有关C ++重载的前三篇文章在这里,这里和这里。
本文是关于数组的。数组可以归因于C ++最古老的层,它们来自C的第一个版本。尽管如此,数组还是包含在C ++的面向对象类型系统中,尽管有一些注意事项。对于程序员来说,了解这些功能很重要,以避免潜在的错误。本文还探讨了另一个C遗留物-普通类型和未初始化的变量。C ++ 11的某些创新会影响数组的工作;所有这些新功能也将详细介绍。因此,让我们尝试讲述有关数组的所有信息。
目录
1.一般规定
数组是最简单的聚合类型。他对在连续内存段中排成一行的一组相似元素进行建模。几乎所有编程语言都支持一种形式或另一种形式的数组,并且毫不奇怪,它们出现在C的第一个版本中,然后成为C ++的一部分。
1.1。数组声明
如果在编译时评估了T
某些类型,N
常量或表达式,则该指令
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"];
, 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';
++rr[0];
rr[1].get() = 125;
std::cout << u << ' ' << v << '\n';
.
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;
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);
— . (, ).
.
int A[4];
extern int A[];
.
auto
.
int a[4];
auto da = a;
template<typename T>
void Foo(T t);
, .
. ( C .) .
class B {};
class D : public B {};
void Foo(B[], int size);
.
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;
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;
, .
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;
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;
&
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];
[]
, , . .
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;
}
};
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,尼古拉·M·C ++标准库:参考指南,第二版。来自英语 -M .: LLC“ I.D. 威廉姆斯,2014年。