它是否始终有效 C++将成员函数指针与 0 进行比较?
在以下代码中,Visual Studio 编译器不会引发断言,但使用 XCode 为 iPhone 进行编译时会引发断言:
class X
{
public:
virtual void A() {}
};
X x;
void main()
{
// Define a valid member function pointer to X::A.
void (X::*p)() = &X::A;
assert(p != 0);
}
这是编译器中的错误吗?在这种情况下,还能如何检查空指针呢?
In the following code, the assertion is not raised with the Visual Studio compiler, but it is raised when compiling for the iPhone using XCode:
class X
{
public:
virtual void A() {}
};
X x;
void main()
{
// Define a valid member function pointer to X::A.
void (X::*p)() = &X::A;
assert(p != 0);
}
Is this a bug in the compiler? How else can one check for a null pointer in this case?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
代码是正确的,编译器不符合标准,该标准表示(部分
[expr.eq]
,使用 C++0x 草案 n3225 中的措辞,但它应该与其他版本):,并且
空指针常量的相关定义(
[conv.ptr]
节,std::nullptr_t
部分是C++0x中新增的):和(
[expr.const]
部分):注意:顺便说一句,指向虚拟成员函数的指针的实现定义表示通常是虚拟表的索引,在问题中为 0。但根据标准,断言内的表达式并不检查表示形式是否为零,而是检查零文字 - 这是空指针检查。
苹果编译器显然将两者混为一谈。如果您想测试表示形式是否为零,您可以编写
assert((intptr_t)p != 0)
——这将是完全不可移植的。但是所编写的代码对于任何符合标准的编译器都是完全可移植的,并且永远不会断言。
编辑:还有一个来自标准的引用,它只是重复了我们已经学到的内容(
[conv.mem]
部分):The code is correct, the compiler is out of compliance with the standard, which says (section
[expr.eq]
, using the wording from C++0x draft n3225, but it should be the same in other versions):and
relevant definition of null pointer constant (section
[conv.ptr]
, thestd::nullptr_t
part is new in C++0x):and (section
[expr.const]
):NOTE: As an aside, the implementation-defined representation of pointer-to-virtual-member-function usually is an index into the virtual table, which would be 0 in the question. But according to the standard, the expression inside the assert isn't checking if the representation is zero, it's checking against a zero literal -- it is a null pointer check.
And the Apple compiler apparently mixed the two up. If you wanted to test if the representation is zero, you could write
assert((intptr_t)p != 0)
-- and that would be completely non-portable.But the code as written is perfectly portable, to any standard-compliant compiler, and will never assert.
EDIT: And one more citation from the standard, which just repeats what we've already learned (section
[conv.mem]
):iPhone 编译器出错了。
请注意,指向虚拟函数的成员函数指针之间的相等比较会产生未指定的结果,即
从形式的角度来看,此断言的行为是不可预测的。
但是成员函数指针与空指针常量的比较是由语言严格定义的。在您的示例中,指针不能为空,因此它不应该与空指针常量进行比较。
The iPhone compiler gets it wrong.
Note that equality comparison between member function pointers that point to virtual functions produces unspecified result, i.e. this assertion
behaves unpredictably from the formal point of view.
But comparison of a member function pointers with null-pointer constant is strictly defined by the language. The pointer cannot be null in your example, so it shall not compare equal to a null-pointer constant.