C++内存管理说明

C++ memory management clarification

本文关键字:说明 管理 内存 C++      更新时间:2023-10-16

我是c++的新手。

我有一节Rectangle课。当我创建这样的Rectangle对象时:

Rectangle R1(10,10,90,20);
  • R1是在堆上还是在堆栈上
  • 如果我使用new运算符创建它,那么它会在堆上吗

(一般来说,在c++中创建对象的正确方法是什么?(

据我所知,如果我在没有new的情况下创建它,则对象位于堆栈上,在其生命周期结束时不需要删除。如果真的用新的创建它

Rectangle* R = new Rectangle(1,1,1,1);

它将被放置在堆上,并且将需要使用CCD_。

Rectangle R1(10,10,90,20);

这将创建一个具有"自动"持续时间的变量。当代码流退出作用域时,它会自动销毁。如果它不在函数中,则意味着代码的执行完成。通常(但并非总是(它位于某种堆栈上。

Rectangle* R = new Rectangle(1,1,1,1);
Rectangle* P(new Rectangle(1,1,1,1)); //rarely used

这部分令人困惑:变量R是一个具有自动持续时间的指针(如上所述(。它指向具有"动态"持续时间的Rectangle。通常(但并非总是(动态对象位于某种堆上。只有使用delete R;显式销毁矩形时,才会销毁该矩形。这意味着,如果函数结束,并且没有R的其他副本,则无法删除,并且将保留在内存中,直到程序结束。这被称为内存泄漏。

在C++中,动态内存最好用智能指针(如std::unique_ptr(处理,这样即使代码崩溃,也不会意外忘记删除它。

std::unique_ptr<Rectangle> R(new Rectangle(1,1,1,1));

您所说的许多内容要么是实现细节,要么取决于上下文。考虑一下:

// file.cpp
Rectangle r1(1,2,3,4);
int main()
{
  Rectangle r2 = r1;
  Rectangle * r3 = new Rectangle(r1);
}

这里,r1具有静态存储静止(=永久(寿命,而r2具有[自动]存储也就是说,r1在程序开始时构造,并在结束时销毁(在main返回之后(,而r2在声明时构造,在其作用域(即本例中的函数体作用域(结束时销毁。

指针r3指向动态存储动力学(=手动(寿命Rectangle对象。对象*r3new表达式中复活,并且它只会在用户的请求下通过匹配的delete表达式(或者手动析构函数调用(被销毁。由于我们没有销毁它,这实际上是一个泄漏

关于*r3使用的内存,除了静态成员函数Rectangle::operator new()(如果存在(或全局分配函数::operator new分配该内存之外,什么都不知道。全局版本的内存通常被称为"免费存储"。

(由于r2*r3被构造为r1的副本,因此所有三个对象r1r2*r3被认为是相等的。(

当您考虑成员变量struct Foo { Rectangle r; };时,情况会变得更加有趣。

  1. 创建具有自动存储持续时间的CCD_ 31。这意味着,在实践中,它将被分配在类似堆栈的结构上。不必介意,"堆栈"只是方便和常见。您必须调用new(或者malloc,如果您真的出于某种愚蠢的原因…不要(来动态分配内存。

  2. 请参见上文。

  3. 是的,任何你new你必须delete。通常情况下,类会为您管理此问题。以std::vector<T>为例。您在堆栈上分配vector,但内部数据(即T的数组(是动态分配的。当vector超出作用域时,delete []将在其析构函数中为您动态分配数组,使您可以愉快地不了解底层内存管理的详细信息。