C++の初期化
どうも、最近のC++では初期化構文が統一的になるらしい。だが、丸括弧と波括弧がどう違うか(同じか)理解してない。
#include <iostream> struct Foo { int x; int y; /* // これを定義すると、{x, y} の初期化子が使えなくなる Foo() { x = 0; y = 0; } */ }; // 書き出し std::ostream& operator<<(std::ostream &out, Foo foo) { return out << "[" << foo.x << ", " << foo.y << "]"; } int main(int argc, char *argv[]) { Foo a {2, 3}; Foo b(a); Foo c; Foo d; // Foo e {a}; // これはダメ Foo e = a; d = b; std::cout << "a:" << a << std::endl; std::cout << "b:" << b << std::endl; std::cout << "c:" << c << std::endl; std::cout << "d:" << d << std::endl; std::cout << "e:" << d << std::endl; return 0; }
$ ./a.exe
a:[2, 3]
b:[2, 3]
c:[2686760, 4201222]
d:[2, 3]
e:[2, 3]
やってみたところ、 Foo a {2, 3}; で期待どおりの初期化をしてくれる。Foo c; がゴミで初期化されるので、デフォルトコンストラクタを書くと、Foo a {2, 3} が動かなくなる。自分で書かないとダメになるようだ。Foo e {a}; もダメ、コピーで作るときは丸括弧なのか? イコール使って Foo e = a; も同じようだ。
イコール使う初期化は止めたほうがいい気がする。初期化と代入のセマンティクスが違うのに同じ記号を使うのは混乱を招くから。
代入文 d = b; が動くってことは、デフォルトの代入演算子はコンパイラが勝手に作ってくれるらしい。デフォルトの代入はメモリイメージのコピーなのかな? メンバーにポインターを含むと、単純コピー(浅いコピー)ではたいていは困る。