代码1:
template<class T>
const PtrInterface<T>*
PtrInterface<T>::newRef() const {
PtrInterface<T>* me = (PtrInterface<T>*) this;
++me->references_;
//++this->references_;
return this;
}
代码2:
template<class T>
const PtrInterface<T>*
PtrInterface<T>::newRef() const {
//PtrInterface<T>* me = (PtrInterface<T>*) this;
//++me->references_;
++this->references_;
return this;
}
是否有任何情况,这两个代码块会做不同的事情? 谢谢!
答案 0 :(得分:7)
是否有任何情况下这两个代码块会做不同的事情?
是的,当您使用const
方法时。目前,具有me
的那个调用未定义的行为。原因如下:
如您所知,当您调用成员函数时,会有一个隐式this
指针。当函数标记为this
时,const
指针为const
。以此为例:
struct foo
{
void method1(void);
void method2(void) const;
int i;
};
隐式地,编译器生成(顺便说一句,这是简化的):
void foo::method1(foo* this);
void foo::method2(const foo* this) const;
那么,这两个身体是一样的吗?
foo* me = (foo*)this;
me->i = 1;
// and
this->i = 1;
答案是它取决于,如前所述,它取决于函数的const
- ness。在非const
函数中,它们是相同的:
void foo::method1(foo* this)
{
foo* me = (foo*)this; // this cast is redundant
me->i = 1;
// ...
this->i = 1;
}
但是在const
函数中:
void foo::method2(const foo* this) const
{
foo* me = (foo*)this; // uh-oh! acts like const_cast
me->i = 1; // modifying a const_cast'd variable is undefined behavior
// ...
this->i = 1; // wouldn't compile
}
我们最终剥离了const
。所以,不,他们并不总是一样的。这是C风格演员的危险:它会找到一种方法。顺便说一下,铸造const
本身并不是不确定的行为;它是对所述变量的修改。
你的问题有一个棘手的问题:你的代码不应该编译。与上面的注释代码一样,在const
方法中,您无法修改reference_
。
如果reference_
是mutable
,这是不同的,我猜它可能是(假设你给了我们可编译的代码。)在这种情况下,我不确定第一个样本是否导致对于未定义的行为,因为它首先是mutable
。我不会抓住机会。
答案 1 :(得分:2)
或多或少GMan所说的一切,除了引用_不必是可变的。它也可以是一个覆盖operator ++()的对象,它是一个const成员函数。