这个C++静态分析规则是否有意义?

Stu*_*etz 12 c++ reference language-lawyer reference-binding

我正在实现一些C++静态分析规则,其中一个规则禁止函数返回引用或指向函数引用参数的指针,即以下都是不兼容的:

int *f(int& x) { return &x; } // #1
const int *g(const int& x) { return &x; } // #2
int& h(int& x) { return x; } // #3
const int& m(const int& x) { return x; } // #4
Run Code Online (Sandbox Code Playgroud)

为此给出的理由是"它是实现定义的行为,无论引用参数是临时对象还是对参数的引用."

然而,我对此感到困惑,因为C++中的流操作符是以这种方式编写的,例如

std::ostream& operator<<(std::ostream& os, const X& x) {
    //...
    return os;
}
Run Code Online (Sandbox Code Playgroud)

我认为我非常有信心C++中的流操作符通常不会表现出实现定义的行为,所以发生了什么?

根据我目前的理解,我希望#1和#3能够很好地定义,因为temporaries不能绑定到非const引用,所以int& x指的是一个超出范围的实际对象函数,因此返回指向该对象的指针或引用是好的.我希望#2变得狡猾,因为一个临时的本来可以被束缚const int& x,在这种情况下,试图取其地址似乎是一个糟糕的计划.我不确定#4 - 我的直觉是,这也可能是狡猾的,但我不确定.特别是,我不清楚以下情况会发生什么:

const int& m(const int& x) { return x; }
//...
const int& r = m(23);
Run Code Online (Sandbox Code Playgroud)

eca*_*mur 8

正如你所说,#1和#3都很好(虽然#1可以说是糟糕的风格).

#4是出于同样的原因而狡猾#2是; 它允许将const引用传播到其生命周期的临时值.

让我们检查:

#include <iostream>

struct C {
  C() { std::cout << "C()\n"; }
  ~C() { std::cout << "~C()\n"; }
  C(const C &) { std::cout << "C(const C &)\n"; }
};

const C &foo(const C &c) { return c; }

int main() { 
   const C &c = foo(C());
   std::cout << "c in scope\n";
}
Run Code Online (Sandbox Code Playgroud)

这输出:

C()
~C()
c in scope
Run Code Online (Sandbox Code Playgroud)

  • @Arne:他们接受并返回一个非const引用,所以它们很好. (3认同)