struct
{
int a,b;
} s = {5, s.a+1};
規格によれば、上記の例で「sa」と読み、s を a=5 および b=6 に初期化しても安全ですか? もしそうなら、ほとんどのコンパイラはこの規則に従いますか?
(上記は VC10 でコンパイルされます。)
struct
{
int a,b;
} s = {5, s.a+1};
規格によれば、上記の例で「sa」と読み、s を a=5 および b=6 に初期化しても安全ですか? もしそうなら、ほとんどのコンパイラはこの規則に従いますか?
(上記は VC10 でコンパイルされます。)
はい、集合メンバーの初期化が順序付けられているためです。
[dcl.init.aggr] /2 には:
8.5.4 で指定されているように、集合体が初期化子リストによって初期化されると、初期化子リストの要素は、添え字またはメンバーの昇順で、集合体のメンバーの初期化子として取得されます。各メンバーは、対応するinitializer-clauseからコピー初期化されます。
[dcl.init.list] /4 には:
braced-init-listのinitializer-list内で、pack展開 (14.5.3) の結果を含むinitializer-clausesは、出現順に評価されます。つまり、指定されたinitializer-clauseに関連付けられたすべての値の計算と副作用は、 initializer-listのコンマ区切りのリストでそれに続くすべてのinitializer-clauseに関連付けられたすべての値の計算と副作用の前に並べられます。
集約メンバーのコピー初期化は確かに副作用 ( [ intro.execution] /12) であり、対応するinitializer-clauseに「関連付ける」必要があります。表現ではありません)。
私が試した最新のコンパイラ (MSVC、Clang、g++) はすべて、これを正しくコンパイルします。一部の古いコンパイラが間違っている可能性があります (g++ の古いバージョンは、集計初期化子の順序付けが間違っていることが知られていました)。