メンバ初期化子リストもつ構造体の配列で戸惑ったのでまとめ。
コンストラクタを持つ構造体
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