指针地址和参考混乱

Pointer address and reference confusion

本文关键字:混乱 参考 地址 指针      更新时间:2023-10-16

我有两个几乎相同的代码,它们应该产生相同的输出,除了它们不仅不同,我更改的一行以某种方式影响了无关的输出!

#include "stdafx.h"
#include <iostream>
using namespace std;
class Tag {
public:
    int num = 0;
    Tag* contains = nullptr;
    Tag::Tag(int n) { num = n; }
    void setContains(Tag t) { contains = &t; }
    int getNum() { return num; }
    Tag getContains() { return *contains; }
};
int main() {
    Tag tag1 = Tag(1); Tag tag2 = Tag(2);
    tag1.setContains(tag2);
    cout << tag1.getContains().getNum() << endl << (*tag1.contains).getNum() << endl;
    return 0;
}

此输出

8460735
8460735

或其他一些随机数。这告诉我我以某种方式输出指针地址,而不是其引用的对象。所以我更改了行

cout << tag1.getContains().getNum() << endl << (*tag1.contains).getNum() << endl;

to

cout << tag1.getContains().getNum() << endl << (*tag1.contains).num << endl;

我得到输出

2
2

等等,什么?如果第二行从地址更改为实际数字2,我会得到它,但是为什么两者都会更改为2?

setContains使 contains指向局部变量。函数返回后,该变量将立即销毁,而contains是悬空的指针。任何尝试使用它的尝试都表现出不确定的行为。

实际上,contains->num从堆叠的堆栈中读取一些随机垃圾,其中变量曾经播放。对程序的轻微扰动会改变堆栈访问模式,在那里留下不同的垃圾。

,因为您调用了未定义的行为,所以您将本地参数的地址保存到Tag* contains

void setContains(Tag t) { contains = &t; }

您应该直接通过参考或指针传递参数。否则,您只是保存在功能退出时被破坏的堆栈上的变量的地址。

之后基于contains的所有内容都是不确定的行为。