即使在离开范围后,您如何访问在 C++ 中分配在堆上的变量?

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

我在理解 C++ 中的 new 关键字时遇到问题。我知道为了在离开范围后不让内存从堆栈中弹出;您可以将其存储在堆上。但是在这个例子中我收到一条错误消息 "identifier p is undefined"

#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 的引用,但错误仍然存​​在。 任何帮助都会很棒! 谢谢

Person* p是一个Pointer*类型的对象,自动存储(一个"local variable")。那个指针,就像任何具有自动存储的对象一样,只存在到声明它的范围的末尾。一旦你到达你创建的块范围的结束 },就没有 [=13= 这样的东西了] 不再存在,该指针已停止存在。

虽然 p 不存在,但它过去指向的内容仍然存在。您的 Person 已泄露并消失。没有指向它的指针或引用,就无法取回它,也无法清理它。确保保留 p 或另一个指向它的指针,直到 delete 它。

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

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

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

你需要的是

int main() 
{
    Person* p;
    {
        p = new Person(5, "bob");
    }

    std::cout << (*p).age; 
}

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

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

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

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是在块中使用,不能从外部调用它。