std::array (c++11)

std::array は、固定長のオブジェクトを保持するシーケンスコンテナで、各要素は連続して格納される。従来のCスタイルの配列のパフォーマンスを保ったまま、シーケンスのサイズの取得、要素の代入のサポートなど、標準コンテナの恩恵を受ける事ができる。また、境界チェック(範囲外の要素にアクセスしようとしていないかのチェック)付きの要素アクセスもサポートしている。

 

 

 

1. 始めに

[概要]

ja.cppreference.com に記載されているサンプルプログラムから作成してみます。
(少し変更しています。)

https://ja.cppreference.com/w/cpp/container/array

 

[環境]

コンパイラ : g++ (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
  Visual Studio 2022, Version 17.2.4
  Visual Studio 2019 pro., Version 16.7.1
OS: Ubuntu, 24.04 (WSL)
  Windows11 home, 21H2
  Windows10 home, Version 1909

 

 

プログラム例: "array_01.cpp"

/**
 * プログラム概要:
 * このプログラムは、C++標準ライブラリの std::array コンテナの基本的な使用方法をデモンストレーションします。
 * 具体的には、配列の初期化(集成体初期化を含む)、コンテナ操作(ソート、リバースコピー)、
 * および範囲forループを使用した要素の出力を行います。
 * std::arrayは固定サイズの配列を提供し、標準コンテナのインターフェースをサポートします。
 */

#include <iostream>     // std::cout
#include <string>       // std::string
#include <array>        // std::array
#include <iterator>     // std::ostream_iterator
#include <algorithm>    // std::sort, std::reverse_copy
 
int main()
{
    // 構築は集成体初期化を使用します。
    std::array<int, 3> a1{ {3, 1, 2} }; // CWG 1270 の改訂前の C++11 では二重の波括弧が必要です
                                        // (改定後の C++11 および C++14 以上では必要ありません)。
    std::array<int, 3> a2 = { 1, 2, 3 };  // = の後では必要ありません。
    std::array<std::string, 2> a3 = { std::string("a"), "b" };
 
    // コンテナ操作がサポートされています。
    // a1
    std::sort(a1.begin(), a1.end());
    std::copy(a1.begin(), a1.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
    // a2
    std::reverse_copy(a2.begin(), a2.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
 
    // 範囲 for ループがサポートされています。
    // a3
    for (const auto& s : a3) {
        std::cout << s << ' ';
    }

    std::cout << '\n';
    
    return 0;
}

 

ビルド方法例(g++):

$ g++ -std=c++23 -Wall -Wextra -Wpedantic array_01.cpp -o array_01.out

 

実行結果:

$ ./array_01.out
1 2 3
3 2 1
a b
$

 

 

2. std::array で二次元配列

 c++11では、std::array はあるけれども std::multi_array がありません。つまり boost::multi_array に相当するコンテナが無いのです。
しょうがないので std::array で multi_array 相当のことができることを以下で確認してみます。たぶん下記のような内容で等価のことをできると判断し、不要と判断されたのかと。
それからイニシャライザーリストの書き方ですが、下記の通り中括弧が3階層必要です。一番外側の中括弧は不要に思えるのですが、これを省略するとエラーになってしまいます。

 

[環境]

コンパイラ : g++ (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
  Visual Studio 2022, Version 17.2.4
  Visual Studio 2019 pro., Version 16.7.1
OS: Ubuntu, 24.04 (WSL)
  Windows11 home, 21H2
  Windows10 home, Version 1909

 

 

プログラム例: "array_02.cpp"

/**
 * プログラム概要:
 * このプログラムは、C++ の `std::array` を使用して 2 次元配列を作成する例を示します。
 * 大きさ `5 x 3` の整数型 2 次元配列を初期化し、各要素をコンソールに出力します。
 * 出力後、ユーザーが Enter キーを押すまで待機します。
 */

#include <iostream> // cout, endl
#include <string>   // string, getline
#include <array>    // array

int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
{
    const std::size_t SIZE_X = 5;
    const std::size_t SIZE_Y = 3;

    std::array<std::array<int, SIZE_X>, SIZE_Y> matrix = {
        std::array<int, SIZE_X>{0, 1, 2, 3, 4},
        std::array<int, SIZE_X>{1, 2, 3, 4, 5},
        std::array<int, SIZE_X>{2, 3, 4, 5, 6},
    };

    // 配列の内容を出力(1)
    for (const auto& row : matrix) {
        for (const auto& value : row) {
            std::cout << value << ' ';
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;

    // 配列の内容を出力(2)
    for ( size_t y=0; y<matrix.size(); ++y ){
        for ( size_t x=0; x<matrix[y].size(); ++x ){
            std::cout << matrix[y][x] << " " ;
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;

    std::cout << "HIT [Enter] KEY !! ";
    std::string input_line;
    std::getline(std::cin, input_line);

    return 0;
}

 

ビルド方法例(g++):

$ g++ -std=c++23 -Wall -Wextra -Wpedantic array_02.cpp -o array_02.out

 

実行結果:

$ ./array_02.out 
0 1 2 3 4 
1 2 3 4 5 
2 3 4 5 6 

0 1 2 3 4 
1 2 3 4 5 
2 3 4 5 6 

HIT [Enter] KEY !! 
$

 

機能としてこれで十分に見えます。固定長配列なので、関数なんかで引数として渡す場合も typedef すればまったく問題を感じませんね。

 

 

3. N次元配列

同じ要領でN次元の配列も作成可能です。
が、型の宣言が std::array< std::array< std::array< ・・・, N3>, N2>, N1> という感じになって面倒です。
何か良い方法がないかとインターネットを検索していたら... よさそうなネタがありました。
結局展開されれば同じことなのですが、わかりやすいこと、template の使い方の良い勉強になること、で素晴らしいコードと思いました。勉強になります。
以下に紹介します。

引用元: http://koturn.hatenablog.com/entry/2018/08/02/000000

 

[環境]

コンパイラ : Visual Studio 2022, Version 17.2.4
  Visual Studio 2010  
OS: Windows11 home, 21H2
  Windows7 Proffesional 64bit 日本語版  

 

[プログラムソース]

#include <iostream>
#include <string>
#include <array>


template<typename T, std::size_t N, std::size_t... Extents>
struct extents_expander
    : extents_expander<std::array<T, N>, Extents...>
{};  // struct extents_expander

template<typename T, std::size_t N>
struct extents_expander<T, N>
{
    using type = std::array<T, N>;
};  // struct extents_expander

template<typename T, std::size_t... Extents>
struct ndarray_helper
{
    using type = typename extents_expander<T, Extents...>::type;
};  // struct ndarray_helper

template<typename T, std::size_t N, std::size_t... Extents>
struct ndarray_helper<T[N], Extents...>
{
    using type = typename ndarray_helper<T, N, Extents...>::type;
};  // struct ndarray_helper

template<typename T>
using NdArray = typename ndarray_helper<T>::type;


int main()
{
    const size_t X = 10;
    const size_t Y = 20;
    const size_t Z = 30;

    static NdArray<int[X][Y][Z]> array;     // NdArray<int[X][Y][Z]> 
                                            // = ndarray_helper<int[X][Y][Z]>
                                            // = ndarray_helper<int[Y][Z], X>
                                            // = ndarray_helper<int[Z], Y, X>
                                            // = ndarray_helper<int, Z, Y, X>
                                            // = extents_expander<int, Z, Y, X>
                                            // = extents_expander<std::array<int, Z>, Y, X>
                                            // = extents_expander<std::array< std::array<int, Z>, Y>, X>
                                            // = std::array<std::array< std::array<int, Z>, Y>, X>

    int count = 0;

    for (int i = 0; i < X; i++) {
        for (int j = 0; j < Y; j++) {
            for (int k = 0; k < Z; k++) {
                array[i][j][k] = count++;
            }
        }
    }

    for (auto x : array) {
        for (auto y : x) {
            std::copy(y.begin(), y.end(), std::ostream_iterator<int>(std::cout, " "));
            std::cout << std::endl;
        }
    }

    return EXIT_SUCCESS;
}

[実行結果]

割愛

 

ライセンス

本ページの情報は、特記無い限り下記 MIT ライセンスで提供されます。

MIT License

Copyright (c) 2012 Kinoshita Hidetoshi

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 

 

 

参考

 


 

変更履歴

2025-11-24 - サンプルコードを更新
2022-06-22 - 評価環境として VS2022、Windows11 を追加
2020-08-18 - 「3. N次元配列」を追加。
2020-08-12 - 画面構成をメンテ。vector, deque の書式と統一。
- "1.始めに" を刷新。
2012-02-26 - 新規作成

 

Programming Items トップページ

プライバシーポリシー