智能指针地址为什么都相等呢?

为什么用智能指针创建临时变量 p1,但是打印的地址都是相等的呢?

class Demo {
public:
    void show() {
        printf("age=%d\n", age);
    }

private:
    const int age = 10;
};

int main() {
    for (int i = 0; i < 10; i++) {
        std::shared_ptr<Demo> p1 = std::make_shared<Demo>();
        printf("%p, %p\n", &p1, p1.get());
    }
  return 0;
}

输出是:
0x16d42f548, 0x122e06808
0x16d42f548, 0x122e06808
0x16d42f548, 0x122e06808
0x16d42f548, 0x122e06808
0x16d42f548, 0x122e06808
0x16d42f548, 0x122e06808
0x16d42f548, 0x122e06808
0x16d42f548, 0x122e06808
0x16d42f548, 0x122e06808
0x16d42f548, 0x122e06808

阅读 2.4k
4 个回答

在为变量、对象分配空间的时候,只要编译器、运行时认为一片空间没有正在被使用,它就有理由复用这一片的空间。

这里的 p1 是循环内部的一个局部变量,它在每次循环的结束的时候就被释放了,它所指向的 Demo 的空间也随着它一起被释放了。所以当下一轮循环开始的时候,编译器、运行时就完全有理由复用上次的空间。所以就看到了每次地址都是相同的。


p1 的空间一般是被编译器分配的,循环体内部的局部变量一般每轮循环都会被放在同一个位置。

Demo 的空间是运行时分配的。具体分配算法得看运行时的具体实现。不过这种同一个类型的变量被连续反复分配释放的情况,放在同一个地址是正常的。在下一次分配的时候,上一次的分配结果已经被释放了。

✅ 你判断 a、b、c 的地址一样不一样,就都一起创建好,然后比较

❌ 不要:创建 a,获取 a 的地址 ,销毁 a;创建 b,获取 b 的地址 ,销毁 b;创建 c,获取 c 的地址 ,销毁 c。再比较。这种方式肯定是错误的

from loguru import logger


class Parser:
    pass


# ❌ 错误的用法
for i in range(10):
    p = Parser()
    print(id(p))

# ✅ 正确的用法
ps = [Parser() for i in range(10)]
for p in ps:
    print(id(p))

这样改一下就好了:

#include <memory>
#include <cstdio>

class Demo {
public:
    void show() {
        printf("age=%d\n", age);
    }

private:
    const int age = 10;
};

int main() {
    std::shared_ptr<Demo> p1;
    for (int i = 0; i < 10; i++) {
        p1 = std::make_shared<Demo>();
        printf("%p, %p\n", &p1, p1.get());
    }
    return 0;
}

GPT4, 参考:

每个循环迭代中创建的临时指针变量p1是不同的,但是它们所包含的指针都指向同一地址,就是Demo对象在堆内存中的位置。因此,在每次循环中打印出来的指针的地址是相同的。因为&p1返回的是指向p1本身的指针,不是指向Demo对象的指针,因此打印出的值相同

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏