回答:
std::initializer_list
格納することを意図したものではなく、単に...初期化のためのものです。内部的には、最初の要素へのポインタとサイズを格納するだけです。コードでは、std::string
オブジェクトは一時的なものであり、initializer_list
どちらもオブジェクトの所有権を取得したり、オブジェクトの寿命を延ばしたり、オブジェクトをコピーしたりしないため(コンテナーではないため)、作成後すぐにスコープから外れますが、オブジェクトinitializer_list
へのポインターは保持されます。そのため、セグメンテーション違反が発生します。
保存には、std::vector
またはのようなコンテナを使用する必要がありますstd::array
。
initializer_list
ます。move-onlyオブジェクトを使用することはできないため、たとえば、unique_ptrのベクターでlist initを使用することはできません。のサイズはinitializer_list
コンパイル時の定数ではありません。そして、完全に異なることstd::vector<int>(3)
をstd::vector<int>{3}
行うという事実。私を悲しくさせます:(
もう少し詳細を追加します。基になる配列はstd::initializer_list
、一時的なものと同様に動作します。次のクラスについて考えてみます。
struct X
{
X(int i) { std::cerr << "ctor\n"; }
~X() { std::cerr << "dtor\n"; }
};
次のコードでのその使用法:
std::pair<const X&, int> p(1, 2);
std::cerr << "barrier\n";
プリントアウト
ctor
dtor
barrier
最初の行から、型の一時的なインスタンスX
が作成され(コンストラクタをから変換することにより1
)、同様に破棄されます。に格納された参照p
はぶら下がります。
についてはstd::initializer_list
、次のように使用すると、
{
std::initializer_list<X> l { 1, 2 };
std::cerr << "barrier\n";
}
次に、基になる(一時的な)配列が存在する限り存在しl
ます。したがって、出力は次のようになります。
ctor
ctor
barrier
dtor
dtor
ただし、
std::pair<std::initializer_list<X>, int> l { {1}, 2 };
std::cerr << "barrier\n";
出力は再びです
ctor
dtor
barrier
基礎となる(一時的な)配列は最初の行にのみ存在するためです。l
then の要素へのポインタを逆参照すると、未定義の動作が発生します。
ライブデモはこちらです。
std::pair
。