即使在离开作用域后,如何访问在堆上分配的变量C++?

How do you access variables that are allocated on the heap in C++ even after leaving the scope?

本文关键字:分配 变量 C++ 访问 作用域 离开 何访问      更新时间:2023-10-16

>我在理解C++中的新关键字时遇到问题。我了解,为了在离开范围后不会从堆栈中弹出内存;您可以将其存储在堆上。但是在此示例中,我收到一条错误消息,指出"标识符 p 未定义"

#include <iostream>
#include <string>
class Person {
public: 
int age; 
std::string name;
Person() {
}
Person(int a, std::string n): age(a), name(n){}
};

int main() {
{
Person* p = new Person(5, "bob");
}
std::cout << (*p).age; 
}

正如您在我的主函数中看到的那样,我创建了另一个作用域,在该作用域中,我在堆上创建了一个 Person 对象,据我所知,该对象在离开大括号后仍然存在,但是为什么它无法识别对象 p?

我尝试取消引用 p,但错误保持不变。 任何帮助都会很棒! 谢谢

您是正确的,该对象仍然存在,因为您从未删除过它。 不过,这只是问题的一半。 名称p是在其中声明它的嵌套范围的本地名称。 退出该作用域后,p将被销毁,您将无法再访问您创建的对象。

你需要的是

int main() 
{
Person* p;
{
p = new Person(5, "bob");
}
std::cout << (*p).age; 
}

现在你可以访问p,因为它是在main的范围内声明的。

>Person* p是一个具有自动存储("局部变量")的Pointer*类型对象。与任何具有自动存储的对象一样,该指针仅在声明它的作用域结束之前存在。一旦你到达你所做的块范围的闭合},就不再有p这样的东西,那个指针已经停止存在。

虽然p不存在,但它过去所指向的东西仍然存在。您的Person泄露并消失了。如果没有指针或对它的引用,就无法将其取回,也无法清理它。确保保留指向它p或其他指针,直到您delete它。

Person* p声明移到范围之外(或完全删除人为范围)将解决此问题。在这种情况下,p的生命周期与main的范围相关联,并且在您尝试std::cout它是age成员时仍然存在。

考虑使用智能指针至少避免这样的泄漏。 当最后一个(也是唯一的)指针不再存在时,std::unique_ptr<Person> p会自动deletePerson

对象仍然存在,如果不删除它,则会出现内存泄漏。如果你想在其他地方访问它,你需要保留对它的引用(一般意义上的引用,即指针或引用)。

但是,该变量只能在声明它的范围内访问。例如,您可以通过执行以下操作来修复它:

int main() {
Person* p;
{
p = new Person(5, "bob");
}
std::cout << (*p).age; 
delete p;
}

问题是当您在大括号之间创建一个变量时,它将具有块范围。

它将在块结束后死亡(指针 p 本身是 32/64 位值,具体取决于您的机器)。 并且 new 分配的内存仍在 堆,但指针本身不是。(这将导致内存泄漏)。

我不知道你到底想做什么,但你可以做

int main() {
Person * ptr;
{
Person* p = new Person(5, "bob");
ptr = p;
}
std::cout << (*ptr).age;
//free the memory if you will not use it anymore
delete ptr;
}

然后,您可以使用 ptr 指向由 new 创建的块。

Person* p  

指针用于存储对象的内存地址,堆上已经分配了内存来存储成员变量,您必须显式使用 Delete 调用默认析构函数来销毁该对象,因为 p 在块中使用,因此不能从外部调用它。