如果您有以下代码,会发生什么?
int mean(const vector<int> & data) {
int res = 0;
for(size_t i = 0; i< data.size(); i++) {
res += data[i];
}
return res/data.size();
}
vector<int> makeRandomData() {
vector<int> stuff;
int numInts = rand()%100;
for(int i = 0; i< numInts; i++) {
stuff.push_back(rand()%100);
}
}
void someRandomFunction() {
int results = mean(makeRandomData());
}
我是否认为C ++只会保留新创建的对象的生命,然后在它超出范围后将其销毁?
此外,这如何工作/干扰RVO?
提前致谢。
编辑:添加了const,忘了把它放进去。
答案 0 :(得分:15)
我的通灵能力告诉我你在Visual C ++上编译它,这就是为什么它甚至可以工作。在标准C ++中,你不能将rvalue(这是makeRandomData
的返回值)传递给引用到非const,所以这个问题没有实际意义。
但是,如果您将mean
的签名更改为const vector<int>&
,则问题仍然有效。在这种情况下,它都归结为临时的生命周期 - 它被定义为持续到它出现的“完整表达式”结束。在您的特定情况下,完整表达式是results
的整个初始化程序。在表达式语句的情况下,完整表达式是整个语句。
标准没有指定函数参数可以抑制RVO的任何方式,但是,当然,RVO是编译器执行特定优化的任务,无论可见的副作用是什么,而不是要求做到这一点。何时(以及如果)RVO发生完全取决于您正在使用的特定编译器。也就是说,似乎没有任何理由可以以任何方式影响它。
答案 1 :(得分:4)
在C ++中,您无法将临时对象传递给采用非常量引用的函数。您在上面发布的示例将无法编译。如果您的编译器编译它,它是编译器的一个怪癖(扩展)。如果编译器在没有发出诊断消息的情况下编译它,那么编译器就会崩溃。
临时对象(makeRandomData()
调用的结果)只能通过const限定引用传递给mean
。即您的mean
必须声明为
int mean(const vector<int> & data)
在这种情况下,引用将直接绑定到makeRandomData()
返回的临时对象,或绑定到编译器可能选择创建的临时对象的另一个副本。 (在这种情况下,后者不太可能,但理论上可能会发生。)