如果某些函数f
分别使用参数p_1
,...,p_n
类型T_1
,...,T_n
调用参数a_1
a_n
,..., function getPhotoEarnings(){
var earnings = [];
var relevantTable = $("a[class='link']").closest("table");
var trs = relevantTable.find("tr");
for(var i=2;i<trs.length-1;i++){
var tds = $(trs[i]).find("td");
var firstId = $(tds[0]).find("a").html();
var firstName = $(tds[1]).find("img").attr("title");
var firstEarned = $(tds[3]).html();
var secondId = $(tds[5]).find("a").html();
var secondName = $(tds[6]).find("img").attr("title");
var secondEarned = $(tds[8]).html();
earnings.push({
"id":firstId,
"name":firstName,
"earned":firstEarned
});
earnings.push({
"id":secondId,
"name":secondName,
"earned":secondEarned
});
}
return earnings;
}
及其正文抛出异常,完成或返回,参数的破坏顺序是什么?为什么?如果可能,请提供标准参考。
编辑:我实际上想询问函数&#34;参数&#34;,但是作为T.C. Columbo设法澄清了我的困惑,我把这个问题留下来,并问a new separate question about the parameters。有关区别,请参阅有关此问题的评论。
答案 0 :(得分:21)
我没有在标准中找到答案,但我能够在3个最受欢迎的C ++兼容编译器上进行测试。 R Sahu 的答案几乎解释了它是实现定义的。
§5.2.2/8:对后缀表达式和参数的评估都是相对于一个没有排序的 另一个。在输入函数之前,对参数评估的所有副作用进行排序。
Visual Studio C ++编译器(Windows)和gcc(Debian)
参数的构造顺序与其声明相反,并以相反的顺序销毁(因此按照退化的顺序销毁):
2
1
-1
-2
Clang(FreeBSD)
参数按其声明顺序构建,并按相反顺序销毁:
1
2
-2
-1
所有编译器都被指示将源代码视为C ++ 11,并使用以下代码片段来演示这种情况:
struct A
{
A(int) { std::cout << "1" << std::endl; }
~A() { std::cout << "-1" << std::endl; }
};
struct B
{
B(double) { std::cout << "2" << std::endl; }
~B() { std::cout << "-2" << std::endl; }
};
void f(A, B) { }
int main()
{
f(4, 5.);
}
答案 1 :(得分:14)
在§5.2.2[4]中N3337对发生的事情非常明确(online draft):
在参数初始化期间,实现可以通过将关联参数的转换和/或临时构造与前者相结合来避免构建额外的临时值。 初始化参数(见12.2)。参数的生命周期在定义它的函数返回时结束。
例如在
中f(g(h()));
来自调用h()
的返回值是一个临时值,将在完整表达式结束时销毁。但是,允许编译器避免这种临时性,并使用其值g()
直接初始化。在这种情况下,返回值将在g()
返回后被销毁(即在调用f()
之前)。
如果我正确理解标准中所述的内容,则不允许将h()
返回的值保留到完整表达式的末尾,除非复制(参数)且此副本为g()
返回后销毁。
这两种情况是:
h
返回值用于直接初始化g
参数。 g
返回时和调用f
之前销毁此对象。h
返回值是暂时的。副本用于初始化g
参数,并在g
返回时销毁。相反,原始临时表在完整表达式的末尾被销毁。我不知道实施是否遵循相关规则。
答案 2 :(得分:11)
标准未指定评估函数参数的顺序。从C ++ 11标准(online draft):
5.2.2函数调用
8 [注意:后缀表达式和参数表达式的评估都是相对于彼此无法排序的。参数表达式评估的所有副作用在函数之前排序 输入(见1.9)。 -end note ]
因此,完全取决于实现来决定评估函数参数的顺序。反过来,这意味着参数的构造顺序也依赖于实现。
合理的实现会以与构造相反的顺序破坏对象。