C++標準ライブラリの文字列型std::string*1 とリテラル0を用いた初期化に関するメモ。
2021-07-02追記:C++2b(C++23)に向けてP2166R1が採択され、nullptr_tを取るstd::string/std::string_viewコンストラクタはdelete宣言される。この仕様追加によって本記事にあるs1, s2, s3はいずれもコンパイルエラーとして検出される。
#include <string> std::string s1 = 0; // NG: 未定義動作 std::string s2(0); // NG: 未定義動作 std::string s3 = (0); // NG: 未定義動作 std::string s4{0}; // OK: 空文字列""で初期化 std::string s5 = {0}; // OK: 空文字列""で初期化
s1,s2,s3ではコンストラクタbasic_string(const char*, const A& = A())が選択され、第1引数にはヌルポインタが渡されるためライブラリ要件違反により未定義動作(undefined behavior)を引き起こす。s4,s5ではオーバーロード解決において初期化子リスト・コンストラクタが最も優先されるため*2、コンストラクタbasic_string(initializer_list<char>, const A& = A())が選択され、その引数にchar型の初期化子リスト{ '\0' }が渡されて空文字列""による初期化が行われる。
C++11(N3337) 21.4.2/p9, p16より引用。
basic_string(const charT* s, const Allocator& a = Allocator());
9 Requires:sshall not be a null pointer.
basic_string(initializer_list<charT> il, const Allocator& a = Allocator());
16 Effects: Same asbasic_string(il.begin(), il.end(), a).
関連URL