更新 2
因此,经过一些研究,我意识到这实际上是很好定义的,尽管评估顺序是未指定的。将各个部分放在一起非常有趣,尽管对于C++11 案例有一个更一般的问题,但没有涵盖C ++11之前案例的一般问题,所以我最终创建了一个自我回答问题,初始化程序中同一变量的多个突变是否列出了涵盖所有细节的 C++11 之前的未定义行为。
基本上,看到时的本能makeX(count++), makeX(count++)
是将整个事物视为一个完整的表达式,但事实并非如此,因此每个初始化器都有一个序列点。
更新
正如 James 指出的那样,它可能不是未定义的C++11之前的版本,它似乎依赖于将每个元素的初始化解释为一个完整的表达式,但目前尚不清楚您是否可以肯定地做出这样的声明。
原来的
在C++11之前,在一个序列点内多次修改变量是未定义的行为,我们可以看到,通过查看旧标准草案中的相关部分将是5
表达式第4节,它说(强调我的):
[...]在前一个和下一个序列点之间,一个标量对象的存储值最多只能通过表达式的评估修改一次。此外,只能访问先验值以确定要存储的值。对于完整表达式的子表达式的每个允许排序,都应满足本段的要求;否则行为未定义。
在C++11 草案标准中,这发生了变化,并从1.9
程序执行第15段中的以下措辞说(强调我的):
除非另有说明,对单个运算符的操作数和单个表达式的子表达式的求值是无序的。[...]如果标量对象的副作用相对于同一标量对象的另一个副作用或使用同一标量对象的值的值计算是无序的,则行为未定义。
我们可以看到,对于8.5.4
List-initialization第4节中的初始化列表来说:
在一个花括号初始化列表的初始化列表中,初始化子句,包括任何由包扩展 (14.5.3) 产生的子句,按照它们出现的顺序进行评估。也就是说,与给定初始化子句相关联的每个值计算和副作用在初始化器列表的逗号分隔列表中与任何初始化子句相关联的每个值计算和副作用之前进行排序。