C++内存管理澄清

发布于 2024-12-11 01:58:41 字数 427 浏览 0 评论 0原文

我是 c++ 新手。

我有一个 Rectangle 类。当我创建如下所示的 Rectangle 对象时:

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

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

据我了解,如果我在没有 new 的情况下创建它,则该对象位于堆栈上,不需要在最后删除其生命周期。如果使用 new 创建它,

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

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

I'm new to c++.

I've got a Rectangle class. When I create a Rectangle object like this:

Rectangle R1(10,10,90,20);
  • Does R1 sit on the heap or stack?
  • If I were to create it using the new operator, would only then it be on the heap?

(In general what would be the correct way to create an object in c++?)

To my understanding, if I create it without new the object sits on the stack and does not need to be deleted at the end of its life time. And if do create it with new

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

it will be placed on the heap and would need to be de-allocated using delete.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

﹉夏雨初晴づ 2024-12-18 01:58:41
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 是一个具有自动持续时间的指针(如上所示)。它指向一个具有“动态”持续时间的矩形。通常(但并非总是)动态对象位于某种堆上。仅当您使用 delete R; 显式销毁矩形时,该矩形才会被销毁。这意味着如果函数结束并且没有 R 的其他副本,则无法删除它,并且将保留在内存中直到程序结束。这称为内存泄漏。

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

std::unique_ptr<Rectangle> R(new Rectangle(1,1,1,1));
Rectangle R1(10,10,90,20);

This creates a variable with "automatic" duration. It is automatically destroyed when the code flow exits the scope. If it's not in a function, that means when the execution of your code completes. Usually (but not always) it sits on some sort of stack.

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

This part is confusing: The variable R is a pointer with automatic duration (like above). It points at an Rectangle with "dynamic" duration. Usually (but not always) the dynamic object sits on some sort of heap. The rectangle is destroyed only when you explicitly destroy it with delete R;. This means if the function ends and there is no other copy of R, it becomes impossible to delete, and will remain in memory until your program ends. This is called a memory leak.

In C++, dynamic memory is best handled with a smart pointer, such as std::unique_ptr, so that you can't accidentally forget to delete it, even if the code is crashing.

std::unique_ptr<Rectangle> R(new Rectangle(1,1,1,1));
深巷少女 2024-12-18 01:58:41

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

// file.cpp

Rectangle r1(1,2,3,4);

int main()
{
  Rectangle r2 = r1;
  Rectangle * r3 = new Rectangle(r1);
}

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

指针r3指向动态存储动态(=手动)生命周期矩形对象。对象 *r3new 表达式中生效,并且只会在用户请求时通过匹配的 delete 表达式(或也许是手动析构函数调用)。由于我们没有销毁它,这实际上是一个泄漏

关于 *r3 使用的内存一无所知,除了该内存是由静态成员函数 Rectangle::operator new() 分配的> 如果存在,否则由全局分配函数 ::operator new 实现。全局版本的内存通常称为“自由存储”。

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

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

Lots of the things you say are either implementation details or dependent on the context. Consider this:

// file.cpp

Rectangle r1(1,2,3,4);

int main()
{
  Rectangle r2 = r1;
  Rectangle * r3 = new Rectangle(r1);
}

Here r1 has static storage and static (= permanent) lifetime, while r2 has automatic storage and automatic (= scoped) lifetime. That is, r1 constructed at program start and destroyed at the end (after main returns), while r2 is constructed at declaration and destroyed at the end of its scope (i.e. the function body scope in this case).

The pointer r3 points to a Rectangle object of dynamic storage and dynamic (= manual) lifetime. The object *r3 comes to life at the new expression, and it will only be destroyed at the user's request via a matching delete expression (or perhaps a manual destructor call). Since we don't destroy it, this is in fact a leak.

Nothing is known about the memory used by *r3, other than that this memory is allocated by the static member function Rectangle::operator new() if it exists, or otherwise by the global allocation function ::operator new. The global version's memory is typically referred to as the "free store".

(All three objects r1, r2 and *r3 are supposedly equal, since r2 and *r3 are constructed as copies of r1.)

The situation gets even more interesting when you consider member variables: struct Foo { Rectangle r; };.

喜你已久 2024-12-18 01:58:41
  1. R1 是使用自动存储期限创建的。这意味着,实际上,它将分配在类似堆栈的结构上。你不必介意,“堆栈”只是方便且常见。您必须调用new(或者malloc,如果您出于某种愚蠢的原因确实想要这样做……则不要调用)来动态分配内存。

  2. 见上文。

  3. 是的,您新建的任何内容都必须删除。通常,一个班级会为您管理这个。以 std::vector 为例。您在堆栈上分配向量,但内部数据(即 T 数组)是动态分配的。当向量超出范围时,它会在其析构函数中删除[]为您动态分配的数组,从而使您能够轻松地忽略底层内存管理细节。< /p>

  1. R1 is created with automatic storage duration. This means that, in practice, it will be allocated on a stack-like structure. It doesn't have to be mind you, a 'stack' is just convenient and common. You have to call new (or malloc if you really want to for some silly reason... don't) to allocate memory dynamically.

  2. See above.

  3. Yes, anything you new you must delete. Typically a class will manage this for you. Take for example an std::vector<T>. You allocate the vector on the stack, but the internal data (i.e., an array of T) is allocated dynamically. When the vector goes out of scope it delete []s the dynamically allocated array for you in it's destructor, allowing you to remain pleasantly ignorant of the underlying memory management details.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文