【发布时间】:2021-09-13 02:54:26
【问题描述】:
在 c++17 中,我想初始化一个结构 10 次并将引用它们的 ptr 推入堆栈。我的代码如下所示。
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
stack<TreeNode*> s;
for (int i = 0; i <= 9; i++) {
TreeNode node(i);
s.push(&node);
cout << &node << endl;
}
但是,当我打印在每个循环中初始化的结构的地址时,所有地址都是一样的。
0000003F439BFBA8
0000003F439BFBA8
0000003F439BFBA8
0000003F439BFBA8
0000003F439BFBA8
0000003F439BFBA8
0000003F439BFBA8
0000003F439BFBA8
0000003F439BFBA8
0000003F439BFBA8
这样,就相当于下面的代码
stack<TreeNode*> s;
TreeNode node(-1);
for (int i = 0; i <= 9; i++) {
node.val = i;
s.push(&node);
cout << &node << endl;
}
我知道在 c++ 中,new 用于为堆上的对象分配新的内存块。但是我还是不明白为什么地址是一样的。
如果您能帮助我或给我一些参考,我将不胜感激。
【问题讨论】:
-
地址总是相同的,因为它是一个局部变量。此外,它的生命周期在循环结束时结束,因此存储其地址不是一个好主意,因为您存储了一个指向不再存在的对象的指针。将来使用该指针是未定义的行为。
-
每个循环迭代都会创建一个
node,它会一直存在到迭代结束。在迭代结束时,它的销毁和它的地址可以被另一个实例重用。每次迭代,您都会保存一个指向 不同node的指针,该指针恰好与不再存在的旧TreeNode对象具有相同的地址。 -
谢谢!但是当我在循环中使用
new初始化节点时,每个循环的地址都不一样。这是否意味着如果一个变量用new初始化,如果我从不手动释放它,它的生命周期将一直持续到整个程序结束? -
@Rinne:正确。我们甚至有一个术语“忘记删除新的对象”,称为内存泄漏。
-
@Rinne 是的,
new的目的是当您需要一个比函数范围更长的对象时。但在现代 C++ 中,它很少使用。一旦确定不再需要该对象,您完全有责任记住使用delete最终销毁该对象。有更安全的替代方案,例如std::make_unique或std::make_shared应该是首选。
标签: c++ loops memory struct c++17