Seb*_*ski 3 c++ reference visual-c++
看看下面的代码.这里的目标是通过两个函数(from ReferenceProvider::getReference()到getRef()to main())返回一个引用:
#include <tchar.h>
#include <assert.h>
#include <string>
class BaseClass {
public:
virtual void write() const {
printf("In base class\n");
}
};
typedef BaseClass* BaseClassPointer;
class ChildClass : public BaseClass {
public:
virtual void write() const {
printf("In child class\n");
}
};
typedef ChildClass* ChildClassPointer;
//////////////////////////////////////////////////////////////////////////
ChildClass* g_somePointer = new ChildClass();
class ReferenceProvider {
public:
const BaseClassPointer& getReference() {
const BaseClassPointer& val = g_somePointer;
return val;
}
};
ReferenceProvider g_provider;
const BaseClassPointer& getRef() {
std::string test;
const BaseClassPointer& val = g_provider.getReference();
return val;
}
int _tmain(int argc, _TCHAR* argv[]) {
BaseClass* child = getRef();
assert(child == g_somePointer);
child->write();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在,在调试此代码时(在Visual C++中),打破return val;in getRef()将为您提供如下屏幕:

注意g_somePointer和的值是如何val相同的.现在,跳过return语句,你会得到一个这样的屏幕:

注意如何val变为无效(0xcccccccc).这可能是因为堆栈getRef()已被清除且val不再可用.
现在的问题是childin _tmain()会使这个无效的值(0xcccccccc)呈现child无法使用.所以我的第一个(也是主要的)问题是:如何正确地做到这一点?
(请注意,这只是我一直在研究的其他代码中的一个简单示例.它需要像使用结构一样,包括使用对指针的引用.)
是什么让整个事情变得非常奇怪(并且难以调试)是该函数getRef()在某些条件下工作:
g_somePointer来BaseClass*(自ChildClass*)getRef()(即行std::string test;)在这两种情况下,引用变量val(in getRef())都不会变为无效,函数将返回正确的指针地址.任何人都可以向我解释一下吗?
问题出在这里:
const BaseClassPointer& val = g_somePointer;
Run Code Online (Sandbox Code Playgroud)
由于g_somePointer具有不同的类型(ChildClass*可转换为BaseClass*,但不是同一类型),val不能直接引用g_somePointer.而是创建一个临时副本,转换为正确的类型,并val引用它.
临时只持续val,在函数末尾超出范围,因此函数返回无效引用.
如果将g_somePointer的类型更改为BaseClass*(来自ChildClass*)
在这种情况下,不需要指针转换,因此val可以直接引用g_somePointer.代码是正确的,但很脆弱.
如果你在getRef()中删除局部变量(即行std :: string test;)
使用字符串变量,在函数末尾有一个析构函数调用,它会覆盖包含临时指针的已解除堆栈的帧.没有它,没有任何东西会覆盖内存,因此代码似乎有效 - 这是不幸的,因为它使错误更难以注意到.
| 归档时间: |
|
| 查看次数: |
391 次 |
| 最近记录: |