堆栈与堆C++
Stack vs Heap C++
我刚刚有一个关于堆栈变量与堆变量如何工作的快速问题。据我了解,堆栈变量是在函数返回后将被删除的变量,而堆变量是持久的。但我真正困惑的是如何在函数中分配堆变量:
int MyObject::addObject(const char* a){
MyObject newObject(a);
return 0;
}
假设我有一个MyObject
的构造函数,它是newObject(const char * a)
.那么在这个函数中,当它被调用时,在返回之后,新构造的newObject
是否被删除?如果是,那么如何分配给函数中的堆呢?如果没有,你以后如何清理你的内存?
此外,析构函数的作用究竟是什么,何时调用?
类MyObject
的构造函数是MyObject()
,而不是newObject()
。在您的示例中,newObject
是变量的名称,而不是构造函数。
要在函数内的堆上进行分配,您需要调用 new
运算符:
int MyObject::addObject(const char* a){
MyObject* newObject = new MyObject(a);
//newObject is allocated on the heap
//... Some more code...
delete newObject;
//you have to explicitly delete heap-allocated variables
//if not, you get memory leaks
return 0;
}
您的代码:
MyObject newObject(a);
创建一个名为 newObject
的自动存储(堆栈(MyObject
,该存储(堆栈(一直存在到声明的范围结束 - 即关闭}
。
此外,析构函数的作用究竟是什么,何时调用?
为了清理内存,分配了new
或new[]
(或malloc
(的类,并且它拥有。当对象超出自动对象的范围时,或者当您为动态对象显式调用delete
时,将调用它。
堆栈内存是你所说的,但更具体地说,它是当前范围的本地内存。 请注意,根据您所说的范围,此内存可以是全局的,也可以是函数或类的本地内存。 一旦它们超出范围,就会清理它们。
通过 new
运算符分配的堆内存。即使在指向内存的所有指针都超出范围之后,这些仍将保留在内存中。 您必须自己在C++中通过 delete
显式释放此内存。 如果不这样做,除非使用智能指针,否则将导致内存泄漏。
另一件需要注意的事情,采用以下示例代码:
void foo()
{
int *bar = new int; //creates a pointer to an int on the stack, but initializes an int on the heap
*bar = 3; //sets the int being pointed to to 3
delete bar; //deletes the int
bar = 0; //removes the now invalid reference
}
指针本身 bar 是在堆栈上创建的。 但是,数据由柱线指向。*酒吧 - 是的,星号在这里确实有所不同。 它为您提供指针指向的数据 -- 在堆上。 当 foo 返回时,酒吧将超出范围。 如果我不调用删除,我将无法访问 *bar 并会出现内存泄漏。
对于第二个问题,dtor 的作用是清理您构建的对象。 默认情况下为您提供一个,但有时您需要编写自己的。 例如,如果您的类中包含原始指针,则需要在 dtor 中使用 delete 显式释放它们。 当对象超出堆栈内存的范围时,以及为堆内存调用删除时,将调用它。
int addObject(const char* a){
MyObject newObject(a);
return 0;
}
此代码在堆栈上分配 newObject。它是在进入函数时构造的(MyObject 构造函数在堆栈内存块上调用(。 当函数在从堆栈中弹出内存块之前返回时,它被销毁(在该实例上调用 MyObject 析构函数(。
MyObject *foo = new MyObject(a);
此代码在堆上分配一个对象。构造函数在分配了一些堆内存后由 new 运算符调用。不会释放内存,也不会调用析构函数,直到您明确表示已使用 delete 关键字完成此操作。
delete foo;
这可以是程序中所需的任何位置。
-
堆栈是函数和方法调用中使用的区域。它基本上用于存储参数和函数本地数据(以及调用函数过程中涉及的其他内容(。堆栈是一种后进先出类型的数据结构,这意味着您输入的最后一件事就是您从中得到的第一件事。
另一方面,堆 是一个免费存储,我的意思是你可以从堆中获取任何值,无论它被放入何处 - 这种区别很重要。
在 C++ 中,每次调用
new
在堆上创建对象并返回指向该对象的指针时,都可以使用该指针访问对象。这既适用于复杂对象,例如您或其他人创建的类中的对象,也适用于内置类型,例如 int、char、double 等......使用 new 没有什么神奇的,它的核心只是调用malloc
,或者根据平台的不同调用它的某种风格,然后调用对象的构造函数。您必须记住为使用new
创建的每个对象调用delete
(或delete []p_array_of_object_pointers
(。析构函数只不过是当您在代码中执行
delete my_object_pointer
时语言对对象调用的函数。析构函数让您有机会在代码中进行一些清理。在 C++ 等语言中,您必须管理自己的资源,您通常会使用它来调用delete
或free
您在堆上分配的其他对象,或者关闭您使用 fopen 等创建的文件句柄......这两个关键字都可以在函数和方法的内部或外部工作,无论您从何处调用它们,它们都将始终与堆一起使用。您在不使用
new
的情况下创建的任何内容最终都会出现在其他地方,无论是可执行文件的静态区域还是堆栈,具体取决于它的创建方式和位置。每次使用以下语法在方法或函数中创建对象时
MyClassType myObject(contructor, arguments);
并且不使用new
,您是在堆栈上创建它(除非您将其声明为静态,这是当它最终出现在我上面提到的静态区域时(。
希望这有帮助。
堆分配是使用 new
关键字完成
C++没有垃圾回收,堆分配永远不会自动释放
您可以使用delete
关键字释放它们
您需要为此保留一个指针,例如,通过从函数返回它,或将其分配给全局变量
析构函数在delete
上调用,用于释放资源,例如网络套接字
因此,代码将是,例如return new MyObject("foo");
您在示例中在堆栈中分配内存。它是自动变量,它将被删除,然后返回发生。如果使用关键字new
则必须提供正确的释放
MyObject* newObject = new MyObject(a);
如何分配到堆:使用new
关键字
如何从堆中释放:使用delete
关键字。
为了避免程序崩溃和内存泄漏,每个new
都必须具有指定对象和类型的delete
对应项。
当对象被删除时,无论它存储在何处(堆、堆栈等(,都会调用析构函数
以下是有关内存的更具体信息:堆栈和堆是什么以及在哪里?
在以下情况下使用动态分配的对象实例:
1(编译时不知道对象的实际类型2(当你要创建的对象数量在编译时是未知的3(当(编译器生成的(对象的生存期管理不能满足您的需求时。
使用 new 运算符创建的每个对象都应在某个时间使用 delete 运算符释放。如果不这样做,就会有内存泄漏,如果你依赖于对象析构函数的副作用,你就不会得到这些副作用,你的程序可能不会做它想要做的事情。
将对象创建为堆栈变量时,编译器将插入代码以在对象超出范围时调用对象析构函数。编译器如何知道要调用什么析构函数?对象的类型在编译时是已知的,因此只有一种可能性,只有一个析构函数要调用。
如果使用"delete"销毁对象,编译器可能无法分辨要使用的析构函数。对象可以是 'basic' 类型,然后析构函数 'basic::~basic((' 将被调用。
class basic;
class derived : public basic
{
....
~derived();
}
basic *l = new derived();
...
delete l;
编译器不知道对象的实际类型不是"基本"而是"派生"。但是,如果将"basic"的析构函数声明为虚拟,则编译器将插入查询对象虚拟方法表的代码,并将调用重定向到正确的析构函数(在本例中,在类型为"派生"的对象上析构函数(。
如果您担心这个问题,如果可以的话,请将析构函数设置为"虚拟"。
- 算法问题:查找从堆栈中弹出的所有序列
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- 为什么调用堆栈数组会导致内存泄漏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的 int main() 中出现堆栈溢出错误
- 堆栈和队列是否像C++中的数组一样传递?
- 拥有映射的现代方法,该映射可以指向或引用已在堆栈上分配的不同类型的数据
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 从堆栈分配的原始指针构造智能指针
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- 堆栈中大小变量输入错误 (C++)
- 堆栈问题(平衡表达式问题集)
- C++ 在堆栈中包含多态属性的类对象存储
- 用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
- 在 C++ 中使用链表进行堆栈
- 变量周围的堆栈'...'已损坏
- 在 gtest 中初始化堆栈上的引用变量的隔离错误
- C++线程的可用堆栈大小