我采取了一些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
对于该给定的理由是,“这是实现定义的参考参数是否是临时对象或所述参数的参考。”
我对这个困惑,但是,因为在C ++流运营商都这样写的,如
std::ostream& operator<<(std::ostream& os, const X& x) {
//...
return os;
}
我觉得我非常有信心,在C ++流运营商在普遍表现出实现定义的行为没有,所以这是怎么回事?
根据我的理解,因为它是目前我所期望的#1和#3被明确定义,即临时工不能绑定到非const引用的基础上,所以int& x
是指具有使用寿命超过一个真正的对象的功能的范围内,因此返回一个指针或引用该对象是好的。 我希望#2是狡猾的,因为暂时可能已绑定到const int& x
,在这种情况下,试图把它的地址会看似不错的计划。 我不知道关于#4 - 我的直觉是,这也是潜在的狡猾,但我不知道。 特别是,我不是在以下情况下会发生什么明显的:
const int& m(const int& x) { return x; }
//...
const int& r = m(23);
正如你所说,#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";
}
这种输出:
C()
~C()
c in scope
在C ++ 11,#2和#4可以,如果有也右值引用过载进行安全的。 从而:
const int *get( const int &x ) { return &x; }
const int *get( const int &&x ) { return nullptr; }
void test() {
const int x = 0;
const int *p1 = get( x ); // OK; p1 is &x.
const int *p2 = get( x+42 ); // OK; p2 is nullptr.
}
所以,虽然他们是狡猾的,他们也有安全使用,如果程序员知道他们在做什么。 这将会是严厉禁止这一点。
(也许更安全的是如果const的右值引用过载是使得私人未定义或以其他方式造成编译时或链接时错误。这是#4的情况下,我们返回一个参考尤其是真实的,但没有什么好返回一个参考和语言不允许引用为null)。