【发布时间】:2012-07-17 07:37:26
【问题描述】:
我正在实现一些 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 是明确定义的,基于临时对象不能绑定到非常量引用,所以 int& x 指的是一个真实的对象它的生命周期超出了函数的范围,因此返回对该对象的指针或引用就可以了。我希望#2 是狡猾的,因为临时可能已绑定到const int& x,在这种情况下,尝试获取其地址似乎是一个糟糕的计划。我不确定#4 - 我的直觉是这也可能是狡猾的,但我不确定。特别是,我不清楚在以下情况下会发生什么:
const int& m(const int& x) { return x; }
//...
const int& r = m(23);
【问题讨论】:
-
@Nawaz:我正在使用 .QL 在大型代码库上编写查询 :) 我认为编译器无关紧要,理想情况下,我正在寻找一个独立于平台的答案。
-
为什么我问是因为 MSVC++ 提供编译器扩展,允许临时绑定到非常量引用。如果你使用的是微软静态分析工具,那么它也可能会考虑这个扩展。
-
@Nawaz:啊,对 :) 在这种情况下,我可能应该为 VC++ 的规则提供一个可选扩展。谢谢! (我不得不说我一般不喜欢这样的编译器扩展。)
-
我没有使用 Microsoft 静态分析工具,它是内部工具 - 但听起来我需要在其中添加一些 Microsoft 特定的东西。
-
您可以通过添加
/Za(禁用语言扩展) 标志来禁用绑定。
标签: c++ reference language-lawyer reference-binding