如果将匿名对象传递给需要引用的函数,C ++中会发生什么?

时间:2010-09-01 22:34:52

标签: c++ reference

如果您有以下代码,会发生什么?

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,忘了把它放进去。

2 个答案:

答案 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()返回的临时对象,或绑定到编译器可能选择创建的临时对象的另一个副本。 (在这种情况下,后者不太可能,但理论上可能会发生。)