std::array - 動的メモリ、ノーサンクス

std::array は、2 つの世界から最高のものを組み合わせます。一方では、std::array は C 配列のサイズと効率を備えています。一方、std::array には std::vector のインターフェースがあります。

std::array は、標準テンプレート ライブラリのすべての順次コンテナーの中で固有の特性を持っています。実行時にサイズを調整することはできません。その初期化には特別な規則があります。

初期化

集計の初期化のルールを覚えておく必要があります:

  • std::array arr :10 個の要素が初期化されていません。
  • std::arrayarr{} . 10 個の要素は値で初期化されます。
  • std::arrayarr{1,2,3,4) :残りの要素は値で初期化されます。

シーケンシャル コンテナーとして、std::array はインデックス アクセスをサポートします。

インデックス アクセス

std::array arr は 3 つの方法でインデックス アクセスをサポートします。

  • arr[n-1]: 配列境界をチェックせずに n 番目の要素にアクセスします。
  • arr.at(n-1): 配列境界をチェックして n 番目の要素にアクセスします。最終的に、std::range_error 例外がスローされます。
  • std::get(arr): コンパイル時に配列境界をチェックして n 番目の要素にアクセスします。構文は std::tuple に従っています。

std::get(arr) は、std::array と std::tuple の関係を示します。 std::array は同種です 固定サイズのコンテナ; std::tuple は異種です 固定サイズのコンテナ

私は、C++ 配列は C 配列と同じくらいメモリ効率が良いと主張しました。証拠がまだありません。

メモリ効率

私の小さなプログラムは、C 配列、C++ 配列、および std::vector のメモリ効率を比較します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// sizeof.cpp

#include <iostream>
#include <array>
#include <vector>
 
 
int main(){
 
 std::cout << std::endl;
 
 std::cout << "sizeof(int)= " << sizeof(int) << std::endl;
 
 std::cout << std::endl;
 
 int cArr[10]= {1,2,3,4,5,6,7,8,9,10};
 
 std::array<int,10> cppArr={1,2,3,4,5,6,7,8,9,10};
 
 std::vector<int> cppVec={1,2,3,4,5,6,7,8,9,10};
 
 std::cout << "sizeof(cArr)= " << sizeof(cArr) << std::endl; 
 
 std::cout << "sizeof(cppArr)= " << sizeof(cppArr) << std::endl;
 
 std::cout << "sizeof(cppVec) = " << sizeof(cppVec) + sizeof(int)*cppVec.capacity() << std::endl;
 std::cout << " = sizeof(cppVec): " << sizeof(cppVec) << std::endl;
 std::cout << " + sizeof(int)* cppVec.capacity(): " << sizeof(int)* cppVec.capacity() << std::endl;

 std::cout << std::endl;
 
}

数字は明確な言語を話します。

C 配列 (22 行目) と C++ 配列 (24 行目) はどちらも 40 バイトを使用します。それはまさに sizeof(int)*10 です。それらとは対照的に、std::vector は追加の 24 バイト (27 行目) を必要とし、ヒープ上のデータを管理します。 cppVec.capacity() は、 std::vector cppVec が新しいメモリを取得せずに持つことができる要素の数です。 std::vector と std::string のメモリ管理の詳細については、STL コンテナーの自動メモリ管理の記事で説明しました。

図を完成させて例を示す前に、はっきりと強調したいことがあります。 C 配列とは対照的に std::array の大きな価値は、std::array がそのサイズを認識していることです。

std::array の動作

C 配列と比較した std::array のもう 1 つの価値は、std::array が std::vector のように感じられることです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// array.cpp

#include <algorithm>
#include <array>
#include <iostream>

int main(){

 std::cout << std::endl;

 // output the array
 std::array <int,8> array1{1,2,3,4,5,6,7,8};
 std::for_each( array1.begin(),array1.end(),[](int v){std::cout << v << " ";});

 std::cout << std::endl;

 // calculate the sum of the array by using a global variable
 int sum = 0;
 std::for_each(array1.begin(), array1.end(),[&sum](int v) { sum += v; });
 std::cout << "sum of array{1,2,3,4,5,6,7,8}: " << sum << std::endl;

 // change each array element to the second power
 std::for_each(array1.begin(), array1.end(),[](int& v) { v=v*v; });
 std::for_each( array1.begin(),array1.end(),[](int v){std::cout << v << " ";});
 std::cout << std::endl;

 std::cout << std::endl;

}

したがって、ラムダ関数と範囲ベースの for ループを使用して、13 行目で array1 を出力できます。 19 行目の合計変数 sum を使用すると、std::array の要素を合計できます。 23 行目のラムダ関数は参照によって引数を取得するため、各要素をその正方形にマップできます。特に特別なことはありませんが、std::array を扱っています。

これがプログラムの出力です。

説明のために

C++11 では、C 配列の反復子を返す無料の関数テンプレート std::begin および std::end があります。そのため、C 配列はサイズを覚えておく必要がないため、これらの関数テンプレートで非常に快適かつ安全に使用できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// cArray.cpp

#include <algorithm>
#include <iostream>

int main(){

 std::cout << std::endl;

 // output the array
 int array1[] = { 1, 2, 3, 4, 5, 6 ,7, 8};
 std::for_each( std::begin(array1), std::end(array1), [](int v){ std::cout << v << " "; });

 std::cout << std::endl;

 // calculate the sum of the array by using a global variable
 int sum = 0;
 std::for_each(std::begin(array1), std::end(array1), [&sum](int v) { sum += v; });
 std::cout << "sum of array{1, 2, 3, 4, 5, 6, 7, 8}: " << sum << std::endl;

 // change each array element to the second power
 std::for_each(std::begin(array1), std::end(array1), [](int& v) { v=v*v; });
 std::for_each(std::begin(array1), std::end(array1), [](int v){ std::cout << v << " "; });
 std::cout << std::endl;

 std::cout << std::endl;
 
}

もちろん、結果は同じです。

次は?

この投稿は簡潔でした。次の投稿では、C++11 の顕著な機能の 1 つであるムーブ セマンティックについて詳しく見ていきます。