gpt4 book ai didi

c++ - 返回时奇怪的 C++ 引用失效

转载 作者:太空狗 更新时间:2023-10-29 19:42:14 27 4
gpt4 key购买 nike

看看下面的代码。这里的目标是通过两个函数(从 ReferenceProvider::getReference()getRef()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;
}

现在,当调试此代码(在 Visual C++ 中)时,在 getRef() 中的 return val; 处中断将给您这样的屏幕:

Breaking a return

请注意 g_somePointerval 的值是如何相同的。现在,跨过 return 语句,您将看到如下屏幕:

Breaking after return

注意 val 是如何变得无效的 (0xcccccccc)。这可能是因为 getRef() 的堆栈已被清除,val 不再可用。

现在的问题是_tmain()中的child会得到这个无效值(0xcccccccc)渲染child 无法使用。所以我的第一个(也是主要)问题是:如何正确地做到这一点?

(请注意,这只是我一直在处理的一些其他代码的浓缩示例。它的结构需要与 with 类似,包括使用对指针的引用。)

让整个事情变得非常奇怪(并且难以调试)的是函数 getRef() 在某些条件下工作:

  1. 如果将 g_somePointer 的类型更改为 BaseClass*(来自 ChildClass*)
  2. 如果您在 getRef() 中删除局部变量(即行 std::string test;)

在这两种情况下,引用变量 val(在 getRef() 中)不会变得无效,函数将返回正确的指针地址.谁能给我解释一下?

最佳答案

问题出在这里:

const BaseClassPointer& val = g_somePointer;

由于 g_somePointer 具有不同的类型(ChildClass* 可转换为 BaseClass*,但不是同一类型), val 不能直接引用 g_somePointer。相反,会制作一个临时拷贝,将其转换为正确的类型,val 会引用它。

临时文件只持续 val,在函数末尾超出范围,因此函数返回无效引用。

If you change the type of g_somePointer to BaseClass* (from ChildClass*)

在这种情况下,不需要指针转换,因此 val 可以直接引用 g_somePointer。代码是正确的,但很脆弱。

If you remove the local variable in getRef() (i.e. the line std::string test;)

对于字符串变量,函数末尾有一个析构函数调用,它会覆盖包含临时指针的失效堆栈帧。没有它,没有任何东西会覆盖内存,因此代码似乎可以工作 - 这很不幸,因为它使错误更难被注意到。

关于c++ - 返回时奇怪的 C++ 引用失效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9065298/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com