即使在离开范围后,您如何访问在 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是在块中使用,不能从外部调用它。
我在理解 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是在块中使用,不能从外部调用它。