C++:参数的引用

3
这个问题的答案指出,你不应该返回参数的引用,因为它们可能是临时变量,可能会超出范围,并且如果结果被分配给引用,则不会被保存。
按照这个逻辑,下面的代码是否有类似的问题?
#include <iostream>

class T
{
  public:
    T& operator+=(const T& t) { this->x += t.x; return *this; }
    T(int x) : x(x) {}
    int x;
    ~T() 
    { 
      std::cout << "My value is " << this->x << " and I'm dead." << std::endl; 
      this->x = -999;
    }
};

int main() 
{
  const T& t = (T(2) += T(3));
  std::cout << t.x << std::endl;
}

如果是这样,我该如何编写 += 运算符以避免此问题?

我还想象中在C++11中以下代码也会有问题,但我还没有检查过:

#include <iostream>
#include <string>

int main()
{
  for ( char x : std::string("hello") += std::string("world") )
  {
    std::cout << x << std::endl;
  }
}

似乎结果表明,除非你愿意在基于范围的for循环中冒着出现未定义行为的风险,否则不应该返回函数参数的引用。
1个回答

1
对于这种情况,返回对*this的引用是预期的行为(这样做是为了启用方法链接)。由于this不是函数的局部变量,因此它不会超出范围。
关于您问题的第二部分,在您的情况下,基于范围的for循环被定义为等同于这个(§6.5.4 [stmt.ranged]):
{
    auto && __range = std::string("hello") += std::string("world");
    for ( auto __begin = begin(__range),
               __end = end(__range);
          __begin != __end;
          ++__begin ) {
        char x = *__begin;
        std::cout << x << std::endl;
    }
}

正如您所看到的,您迭代的字符串是使用auto &&捕获的,它可以绑定 += 返回的常量引用。

编辑 正如Martinho在他的评论中指出的那样,+=返回一个非const引用,因此在那里显示的代码是未定义的行为。


2
auto&& 将绑定一个左值引用,因为这是 operator+= 返回的内容。这不会延长临时对象的生命周期,代码确实是未定义行为。 - R. Martinho Fernandes
@R.MartinhoFernandes:确实,我错了。 - Björn Pollex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接