2008-10-06 80 views

回答

20

5.3。1的标准是“可以采用不完整类型的对象的地址,但是如果该对象的完整类型是声明运算符&()作为成员函数的类类型,那么行为是未定义的(并且没有诊断是必须的)。”

我也不知道这一点,但正如另一张海报指出的,很容易看出它如何导致编译器生成不正确的代码。

0

编辑占到评论:

这是一个猜测,但主要的原因转发声明一个是能够指针声明为该类。编译器必须在定义之前对类进行假设 - 例如指针的大小。

是否可以通过重载运算符&来更改T *的大小? (编辑:评论员 - 我想不是) - 但

什么假设是由超载运算符违反& - 它如何改变类?

这是一种方法。

我可以这样写:

class A; 

void f(A& x) { 
    A* xPointer = &x; 
} 

具有新的意义,如果运营商&()过载比,如果没有,编译器可能认为它可以为它生成代码,但它是错误的。

+0

无论如何,指针的大小都是一样的,不是吗? – 2008-10-06 23:11:34

+0

我相信指针总是相同的大小(这就是为什么编译器可以承担的大小..),除了成员函数指针的情况下,无论如何,这些指针并不是传统意义上的“指针”。 – 2008-10-06 23:14:14

+0

是的,我认为是这样 - 我只是试图从一个前提开始,即声明一个类型的前置点,以便编译器可以在没有完整声明的情况下开始对其进行一些假设。运营商违反了什么假设。 – 2008-10-06 23:14:53

16

我没有听说过,要么,但在此之前给了潜在的混乱结果相同的代码和超负荷后:

#include <iostream> 

class Foo; 

void bar (Foo& foo) { 
    std::cout << &foo << std::endl; 
} 

class Foo { 
public: 
    bool operator &() { return true; } 
}; 

void baz (Foo& foo) { 
    std::cout << &foo << std::endl; 
} 

int main() { 
    Foo foo; 

    bar(foo); 
    baz(foo); 

    return 0; 
} 

输出:

0x7fff092c55df 
1 

虽然还有其他的原因为什么你不会那么做 - 重载地址 - 不能很好地与stl或很多通用的代码搭配使用。

6

我认为这个陈述并不准确。像其他答案一样,我在这里猜测。首先,我假设他们指的是unary operator& and not binary operator&。那就是:

int x = 5; 
int* p = &x; // unary & 
if (x & 1) // binary & 

你可以转发声明你想要的任何类。但是,如果类重载一元运算符&,并且您在指向其中一个对象的指针上调用一元运算符&,则可能会出现不一致的行为(有时您只需获取地址,有时您会调用重载的方法)。这很容易变成几乎无法调试的东西。


我很高兴fizzer实际上看着标准,并不只是猜测。

0

措辞不明确,你当然可以提前申报班级 - 但是显然,这个规则采取了“不应该”的立场,即班级超载operator&

其他编码标准中也存在类似规则,例如JSF(pdf)规则159规定operator&不应重载。

1

由于能够重载运算符&,因此提升库提供了handy template addressof()以负责查找类的实际地址。不是我建议你超载运算符&,但如果需要,可以获得帮助。