2.2.4. 構造体の割り当て方のバリエーション

配列のデータはnewで動的に割り当てるものの、固定長でサイズも小さい Array 構造 体の方は普通の変数として割り当てるという作り方の例です。

前の例とは、 Array の割り当て、解放の関数と main 関数の中だけが違います。

割り当て・解放の関数は次のようになっています。

48// allocate an array.
49// returns true on success, false on failure.
50bool allocate_array_struct(int n, Array *par) {
51    par->pdata = new double[n];
52    if (par->pdata == nullptr) {
53        // could not allocate memory for the array.
54        return false;
55    }
56    // success.
57    par->n_size = n;
58    return true;
59}
60
61void free_array_struct(Array *ar) {
62    delete [] ar->pdata;
63}

前の例との相違点は、 Array は割り当て済みで、その先の parray の部分だけ を割り当て・解放している点です。

65int main(int argc, const char *argv[])
66{
67    std::cout << "s004\n";
68
69    // allocate array dynamically on the heap area.
70    Array array1;
71    Array array2;
72    if (! allocate_array_struct(N_SIZE, &array1)) {
73        return EXIT_FAILURE;
74    }
75    if (! allocate_array_struct(N_SIZE, &array2)) {
76        free_array_struct(&array2);
77        return EXIT_FAILURE;
78    }

Array 型の変数 array1array2 は、 main 関数のローカル変数とし て割り当てています。

 80    // Array型の変数のアドレスを関数に渡す。
 81    // 構造体のコピーを防ぐ昔の書き方(今は参照型を使う)
 82    // 関数の側ではArray型のポインタ変数で受ける。
 83    std::cout << "Before initialization\n";
 84    print_data_struct(&array1);
 85
 86    set_dummy_data_struct(&array1);
 87    std::cout << "After initialization\n";
 88    print_data_struct(&array1);
 89
 90    copy_data_struct(&array2, &array1);
 91    std::cout << "After array copy\n";
 92    print_data_struct(&array2);
 93
 94    // return allocated memory to OS
 95    // new に成功した場合にのみ delete を呼ぶこと。
 96    free_array_struct(&array1);
 97    free_array_struct(&array2);
 98
 99    return EXIT_SUCCESS; // exit status code 0
100}

全体のソースを以下に示します:

  1// s004: dynamically allocated array held on a struct
  2// along with the data count.
  3//
  4// the struct is allocated as a whole value rather than a pointer.
  5//
  6#include <iostream>
  7#include <cassert>
  8
  9const int N_SIZE = 10;
 10
 11// pdataとn_sizeという項目を持つ構造体を宣言する。
 12// Array型の変数が使えるようになる。
 13struct Array {
 14    double *pdata;
 15    int n_size;
 16};
 17
 18// same functions as s001.cpp
 19
 20// function to set dummy data to the array
 21void set_dummy_data_struct(Array *par)
 22{
 23    for (int i = 0; i < par->n_size; i++) {
 24        par->pdata[i] = static_cast<double>(i) / static_cast<double>(par->n_size);
 25    }
 26}
 27
 28void copy_data_struct(Array *pdest, const Array *psrc)
 29{
 30    assert(pdest->n_size == psrc->n_size);
 31    for (int i = 0; i < pdest->n_size; i++) {
 32        pdest->pdata[i] = psrc->pdata[i];
 33    }
 34}
 35
 36void print_data_struct(const Array *par)
 37{
 38    std::cout << "[";
 39    for (int i = 0; i < par->n_size; i++) {
 40        std::cout << par->pdata[i];
 41        if (i < par->n_size - 1) {
 42            std::cout << ", ";
 43        }
 44    }
 45    std::cout << "]\n";
 46}
 47
 48// allocate an array.
 49// returns true on success, false on failure.
 50bool allocate_array_struct(int n, Array *par) {
 51    par->pdata = new double[n];
 52    if (par->pdata == nullptr) {
 53        // could not allocate memory for the array.
 54        return false;
 55    }
 56    // success.
 57    par->n_size = n;
 58    return true;
 59}
 60
 61void free_array_struct(Array *ar) {
 62    delete [] ar->pdata;
 63}
 64
 65int main(int argc, const char *argv[])
 66{
 67    std::cout << "s004\n";
 68
 69    // allocate array dynamically on the heap area.
 70    Array array1;
 71    Array array2;
 72    if (! allocate_array_struct(N_SIZE, &array1)) {
 73        return EXIT_FAILURE;
 74    }
 75    if (! allocate_array_struct(N_SIZE, &array2)) {
 76        free_array_struct(&array2);
 77        return EXIT_FAILURE;
 78    }
 79
 80    // Array型の変数のアドレスを関数に渡す。
 81    // 構造体のコピーを防ぐ昔の書き方(今は参照型を使う)
 82    // 関数の側ではArray型のポインタ変数で受ける。
 83    std::cout << "Before initialization\n";
 84    print_data_struct(&array1);
 85
 86    set_dummy_data_struct(&array1);
 87    std::cout << "After initialization\n";
 88    print_data_struct(&array1);
 89
 90    copy_data_struct(&array2, &array1);
 91    std::cout << "After array copy\n";
 92    print_data_struct(&array2);
 93
 94    // return allocated memory to OS
 95    // new に成功した場合にのみ delete を呼ぶこと。
 96    free_array_struct(&array1);
 97    free_array_struct(&array2);
 98
 99    return EXIT_SUCCESS; // exit status code 0
100}

Download the source code

実行例を示します

% ./s004
s004
Before initialization
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
After initialization
[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
After array copy
[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]