C ++内存管理澄清

时间:2011-10-19 23:27:14

标签: c++ memory-management

我是c ++的新手。

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

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

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

据我了解,如果我在没有new的情况下创建它,则该对象位于堆栈中,并且不需要在其生命周期结束时删除。如果用新的

创建它
Rectangle* R = new Rectangle(1,1,1,1);

它将被放置在堆上,需要使用delete取消分配。

3 个答案:

答案 0 :(得分:4)

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));

答案 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表达式(或者可能是手动析构函数调用)来销毁它。由于我们不销毁它,实际上这是 leak

*r3使用的内存一无所知,除了该内存由静态成员函数Rectangle::operator new()分配(如果存在),或者全局分配分配函数::operator new。全局版本的内存通常被称为“免费商店”。

(所有三个对象r1r2*r3应该相等,因为r2*r3被构造为r1的副本。)

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

答案 2 :(得分:0)

    使用自动存储持续时间创建
  1. R1。这意味着,在实践中,它将被分配在类似堆栈的结构上。它不必介意你,'堆栈'只是方便和常见。你必须调用new(或malloc,如果你真的想要一些愚蠢的理由......不要)动态分配内存。

  2. 见上文。

  3. 是的,new您必须delete的任何内容。通常,课程会为您管理。以std::vector<T>为例。您在堆栈上分配vector,但内部数据(即T的数组)是动态分配的。当vector超出范围时,delete []为其中的动态分配数组提供了析构函数,使您可以对基础内存管理细节保持愉快的了解。