在C,C ++中进行初始化排序

问题描述 投票:18回答:4

考虑以下初始化:

/* C, C++ */
int a[] = { f(), g() };
struct { int x, y } foo = { f(), g() };

/* C++ */
struct goo { goo(int x, int y);  };

goo b = { f(), g() };
goo c { f(), g() };    /* C++11 */
goo d ( f(), g() );

执行顺序f()g()在C和C ++标准指定的任何行中?

c++ c initialization initializer-list
4个回答
20
投票

在所有这两个案例中

goo b = { f(), g() };
goo c { f(), g() };    /* C++11 */

评估顺序从左到右确定,所有副作用应在下一个初始化器之前应用。

来自C ++标准

4在braced-init-list的initializer-list中,initializer-clause(包括pack扩展(14.5.3)中的任何结果)按照它们出现的顺序进行评估。 也就是说,与给定初始化子句相关联的每个值计算和副作用在每个值计算和与初始化列表的逗号分隔列表中跟随它的任何初始化子句相关联的副作用之前被排序。

但是在C中还有其他规则

初始化列表表达式的评估相对于彼此不确定地排序,因此未指定任何副作用发生的顺序。


11
投票

执行顺序f()和g()是否在C和C ++标准指定的任何行中?

在C, 没有 。 他们可以按任何顺序进行评估。

C11 6.7.9初始化

初始化列表表达式的评估相对于彼此不确定地排序,因此任何副作用发生的顺序是未指定的152)

虽然C ++ 11说评估的顺序是确定性的。

8.5.4:4列表初始化

在braced-init-list的initializer-list中,initializer-clauses(包括pack扩展(14.5.3)产生的任何结果) 按照它们出现的顺序进行评估 。 也就是说,与给定初始化子句相关联的每个值计算和副作用在每个值计算和与初始化列表的逗号分隔列表中跟随它的任何初始化子句相关联的副作用之前被排序。


152)特别是,评估顺序不必与子对象初始化的顺序相同。


2
投票

不,在C中,初始化程序的评估顺序未指定:

(C11,6.7.9p23)“初始化列表表达式的评估是相对于彼此不确定地排序的,因此任何副作用发生的顺序都是未指定的.152”

152)特别是,评估顺序不必与子对象初始化的顺序相同。

在C ++中,行为是不同的,初始化器按它们出现的顺序进行评估(C ++ 11,8.5.4p4)。


2
投票

在C ++ 11中,相关部分是8.5.4列表初始化的第4段

内的支撑-INIT-列表初始化列表 ,从包扩展(14.5.3)产生的初始化子句 ,包括任何被以它们出现的顺序进行评价 。 即,与给定的初始值设定子句相关联的每个值的计算和副作用与它后面在初始化列表的逗号分隔的列表中的任何初始化子句相关联的每个值的计算和副作用之前测序。 [ 注意 :无论初始化的语义如何,此评估顺序都保持不变; 例如,当initializer-list的元素被解释为构造函数调用的参数时,它适用,即使通常对调用的参数没有排序约束。 - 结束说明 ]

所以评估顺序是从左到右

请注意,遗憾的是,由于自至少版本4.7.0以来的错误 ,GCC以相反的顺序, 从右到左进行评估。 因此,如果您得到任何意外结果,这可能是一个原因。

© www.soinside.com 2019 - 2024. All rights reserved.