C++动态分配内存

use*_*113 6 c++ memory-management

我不太明白动态分配的内存,我希望你们能让我更清楚.

首先,每次我们分配内存时,我们只需获得一个指向该内存的指针.

int * dynInt = new int;
Run Code Online (Sandbox Code Playgroud)

那么做我上面做的和以下有什么区别:

int someInt;
int* dynInt = &someInt;
Run Code Online (Sandbox Code Playgroud)

据我所知,在这两种情况下,内存都是为int分配的,我们得到一个指向该内存的指针.

那么两者之间的区别是什么.何时一种方法优于另一种方法.

还有更多为什么我需要释放内存

delete dynInt;
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,但不是在第二种情况下.

我的猜测是:

  1. 当为一个对象动态分配内存时,该对象不会被初始化,而如果您执行类似于第二种情况的操作,则该对象将被初始化.如果这是唯一的区别,除了动态分配内存更快的事实之外,还有任何动机.

  2. 我们不需要对第二种情况使用delete的原因是因为初始化对象的事实创建了某种自动销毁例程.

如果有人纠正我并为我澄清事情,那些只是猜测会喜欢它.

Lig*_*ica 15

不同之处在于存储时间.

  • 具有自动存储持续时间的对象是您的"普通"对象,它们在定义它们的块的末尾自动超出范围.

    创建它们就像int someInt;

    你可能听说过它们是"堆栈对象",尽管我反对这个术语.

  • 具有动态存储持续时间的对象具有"手动"生命周期; 你必须自己销毁它们delete,并用关键字创建它们new.

    你可能听说过它们是"堆对象",尽管我也反对这一点.

指针的使用实际上与它们中的任何一个都不是严格相关的.您可以指向自动存储持续时间的对象(第二个示例),并且可以指向动态存储持续时间的对象(第一个示例).

但是你很少需要一个指向自动对象的指针,因为:

  1. 你没有"默认";
  2. 对象不会持续很长时间,所以你用这样的指针做的事情并不多.

相比之下,动态对象通常通过指针访问,因为语法接近强制执行它.new返回一个指针供你使用,你必须传递一个指针delete,并且(除了使用引用)实际上没有其他方法来访问该对象.它生活在一片充满活力的云中,不在当地范围内.

因此,指针的使用有时与动态存储的使用相混淆,但实际上前者与后者没有因果关系.

  • @TamásSzelei:在这种情况下,您应该使用参考. (3认同)

Bjö*_*lex 13

像这样创建的对象:

int foo;
Run Code Online (Sandbox Code Playgroud)

具有自动存储持续时间 - 对象一直存在,直到变量foo超出范围.这意味着在第一个示例中,dynInt一旦someInt超出范围(例如,在函数末尾),将是无效指针.

像这样创建的对象:

int foo* = new int;
Run Code Online (Sandbox Code Playgroud)

具有动态存储持续时间 - 对象一直存在,直到您明确调用delete它为止.

对象的初始化是一个正交的概念; 它与您使用的存储持续时间类型无直接关系.有关初始化的更多信息,请参见此处

  • 要迂腐,你真的对*memory*一无所知,因为这取决于你的分配函数`:: operator new()`的实现.它是动态对象的*生命周期*,即手动:*对象*一直存在,直到你"删除"它为止.C++分离内存分配和对象构造. (2认同)

Sta*_*ked 5

  1. 您的程序在启动时获得一块初始内存。该内存称为堆栈。现在的大小通常在 2MB 左右。

  2. 您的程序可以向操作系统请求额外的内存。这称为动态内存分配。这会在空闲存储(C++ 术语)或(C 术语)上分配内存。您可以请求系统愿意提供的尽可能多的内存(多个 GB)。

在堆栈上分配变量的语法如下所示:

{
    int a; // allocate on the stack
} // automatic cleanup on scope exit
Run Code Online (Sandbox Code Playgroud)

使用自由存储中的内存分配变量的语法如下所示:

int * a = new int; // ask OS memory for storing an int
delete a; // user is responsible for deleting the object
Run Code Online (Sandbox Code Playgroud)


回答您的问题:

何时一种方法优于另一种方法。

  1. 一般来说,堆栈分配是首选。
  2. 当您需要使用其基类型存储多态对象时,需要动态分配。
  3. 始终使用智能指针自动删除:
    • C++03: boost::scoped_ptr,boost::shared_ptrstd::auto_ptr.
    • C++11:std::unique_ptrstd::shared_ptr.

例如:

// stack allocation (safe)
Circle c; 

// heap allocation (unsafe)
Shape * shape = new Circle;
delete shape;

// heap allocation with smart pointers (safe)
std::unique_ptr<Shape> shape(new Circle);
Run Code Online (Sandbox Code Playgroud)

进一步说明为什么我需要在第一种情况下释放内存,但在第二种情况下不需要释放内存。

正如我上面提到的,堆栈分配的变量在作用域退出时自动释放。请注意,您不允许删除堆栈内存。这样做将不可避免地使您的应用程序崩溃。