4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C言語からC++で戸惑ったところ メンバ初期化子リストを持つ構造体の配列

Posted at

メンバ初期化子リストもつ構造体の配列で戸惑ったのでまとめ。
コンストラクタを持つ構造体
vectorも組み合わさってきて混乱した。

メンバ初期化子リストという機能

構造体の中に書かれる見たこと無い関数の書き方に戸惑った。
メンバ初期化子リストという構造体のメンバ(変数)を初期化する機能とのこと。

Edge(int t, int w) : to(t), weight(w) {}

今回は、メンバはconstで宣言されていないので、下記のように書き換えることができるが、メンバがconstで宣言されたときは上記の書き方必要になる。

Edge(int t, int w){
    to = t;
    weight = w;
}

全体のコード

# include <iostream>
# include <vector>
using namespace std;

/* c++では構造体宣言がtypedef宣言も兼ねることになった。 */
struct Edge
{
    int to;
    int weight;
    /* メンバ初期化子リストという機能、constメンバ変数だったときに役に立つ */
    Edge(int t, int w) : to(t), weight(w) {}
};

int main()
{
    /* Edgeを単体で宣言。引数を渡す */
    Edge test1(0, 0);

    /* Edgeを配列で宣言 */
    /* 引数が2つのときは下記の書き方をしなければならない。1個のときは構造体名を省略できる */
    Edge test2[2] = {Edge(0,4),Edge(0,1)};

    /* 引数なしの宣言は不可 */
    // Edge test3[2];

    /* コンテナ宣言(メモリだけ確保された状態) */
    vector<Edge> test4;

    /* アクセスするとVSCodeでは 「Illegal instruction: 4」とエラー */
    // cout << test4[0].to << endl;

    /* コンストラクタがあるため要素を追加するときは一つずつしか出来ない */
    test4.push_back(Edge(1,1));

    /* 要素を入れるとアクセスでき˜るようになる */
    cout << test4[0].to << endl;

    /* constで宣言していないので代入はできる */
    test4[0].to = 5;
    cout << test4[0].to << endl;
    
    return 0;
}

構造体を使った2次元配列 型エイリアス宣言

typedefではなく、型エイリアス宣言というのが使えるようになった。やっていることは同じ。

# include <iostream>
# include <vector>
using namespace std;

struct Edge
{
    int to;
    int weight;
    Edge(int t, int w) : to(t), weight(w) {}
};

/* typedefと同じ。型エイリアス宣言というc++の機能 */
/* using identifier attr = type-id ;の形で宣言される */
// typedef vector<vector<Edge>> Graph;と同義
using Graph = vector<vector<Edge>>;

int main()
{
    /* 宣言はこれでOK。コンテナだからメモリを確保しているだけ */
    Graph TEST(3);

    /* ひとつひとつ代入する必要がある */
    /* 1次元の領域に追加 */
    TEST[0].push_back(Edge(1, 2));
    TEST[1].push_back(Edge(1, 2));
    TEST[2].push_back(Edge(1, 2));

    /* 二次元の領域に追加 */
    TEST[0].push_back(Edge(8, 8));
    cout << TEST[0][1].to << endl;

    return 0;
}

参考

コンテナ【vector】 | C++入門~bituse~
https://bituse.info/cp/10

EffctiveC++入門 コンストラクタでは代入よりも初期化を使う
http://www002.upp.so-net.ne.jp/ys_oota/effec/chapter3.htm#12kou

オブジェクトの配列
http://wisdom.sakura.ne.jp/programming/cpp/cpp9.html

型エイリアス、エイリアステンプレート (C++11以上) - cppreference.com
https://ja.cppreference.com/w/cpp/language/type_alias

4
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?