我在理解C ++中的new关键字时遇到问题。我知道,为了不让内存在离开范围后从堆栈中弹出;您可以将其存储在堆上。但是,在此示例中,我收到一条错误消息,提示“标识符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
设置为delete
。
该对象仍然存在,并且如果不删除它,则会发生内存泄漏。如果要在其他位置访问它,则需要保留对其的引用(一般意义上的引用,即指针或引用)。
问题是,当您在花括号之间创建变量时,它将具有块作用域。