C++动态内存细节

Jun*_*ier 4 c++ memory free memory-management dynamic

我是一名C和Java程序员,因此内存分配和OOP对我来说并不是什么新鲜事.但是,我不确定如何使用C++实现对象来避免内存泄漏.即:

string s1("0123456789");
string s2 = s1.substr(0,3);
Run Code Online (Sandbox Code Playgroud)

s2 现在有一个新的字符串对象,所以它必须通过以下方式释放:

delete &s2;
Run Code Online (Sandbox Code Playgroud)

对?

此外,我是否正确地假设我将不得不删除函数返回的任何(新)对象的地址,无论返回类型不是指针或引用?生活在堆上的对象在必须被释放时不会作为指针返回,这似乎很奇怪.

Bur*_*ard 16

没有.

你只需要释放你分配的内存(即通过new或memalloc).


Joa*_*son 12

没有,

双方s1s2会得到破坏时,超出范围.

s1.substr() 将创建一个您不必考虑的临时对象.


jal*_*alf 8

答案有几层.

首先,变量可以用几种不同的方式声明:

  • 作为局部变量(在函数内部或作为类成员).示例:int i,或int i = 42.它们具有自动存储持续时间(这些示例在技术上是简写auto int i,或者auto int i = 42,尽管auto关键字实际上从未使用过.这意味着这些变量在超出范围时将自动释放.它们的析构函数保证被调用(不无论你如何离开范围,无论是通过函数返回还是抛出异常,它们的析构函数将在它们超出范围时被调用,然后它们使用的内存被释放..这样声明的局部变量被分配在堆栈.
  • 一个静态变量(带有static关键字,暗示静态存储持续时间,而不是上面显示的自动.这些只是在程序的持续时间内保持不变,因此不必释放
  • 在堆上,使用动态分配(new intnew int(42)).这些必须通过调用手动释放delete.

所以在最低级别,你基本上只需保持对称性.如果分配了一些东西new,可以使用delete,malloc is freed byfree , andnew [] bydelete []` 释放它.并且没有任何这些声明的变量会自动处理,不应手动释放.

现在,为了简化内存管理,通常使用RAII.该技术基于以下观察:只有动态分配的对象必须手动释放,并且局部变量为您提供了一个非常方便的钩子,用于在局部变量超出范围时实现自定义操作.

因此,动态分配包含在一个单独的类中,可以将其分配为堆栈中的本地对象.然后,它可以在其构造函数中进行所需的任何动态分配,并且它的析构函数会使用必要的delete调用来清理它.

这意味着你实际上从未有打电话给delete你的顶级代码.它几乎总是隐藏在RAII对象的析构函数后面.new调用变得罕见,但仍然与智能指针一起使用(例如:boost::shared_ptr<int>(new int(42))它动态分配一个整数,然后将其传递给智能指针,该指针接管它的所有权,并自动清理它.


haf*_*fax 5

s1和s2都是自动分配的.你不删除它们.您只能delete使用您创建的对象new.

C++知道三种分配模式:自动,静态和动态.阅读这些内容.自动值(如示例中的字符串)在离开作用域时会自动释放.他们的析构函数会自动调用.调用字符串析构函数时,将释放在操作期间动态分配的字符串的任何内存.