一些涉及类析构函数和删除运算符的内存管理问题?

发布于 2024-11-19 03:48:12 字数 811 浏览 1 评论 0原文

在阅读了一些教程后,我仍然不清楚 C++ 中内存管理的一些观点。

1. 当使用 new 运算符声明的类超出范围时,是否会调用其析构函数并释放内存? 是否有必要调用删除运算符来释放类的内存并调用其析构函数?

class Test{};

void newTest(){
    Test *t = new Test;
}

int main()
{
    newTest();
    return 0;
}

2. 当变量(例如向量)所在的类被销毁时,使用 new 关键字声明的变量(例如向量)是否会被释放? 这些变量是否必须在类的析构函数中显式删除?

class Test{
    vector<int> *vec;
public:
    Test();
};

Test::Test(){
    *vec = new vector<int>;
}

void newTest(){
    Test t;
}

int main()
{
    newTest();
    return 0;
}

3. 与问题 2 相同,但使用在堆栈上声明的普通变量。 在下面的示例中,当 t 超出范围时,向量 vec 是否被删除?

class Test{
    vector<int> vec;
};

void newTest(){
    Test t;
}

int main()
{
    newTest();
    return 0;
}

4. 最后,在类中声明向量的更好方法是通常(在堆栈上)还是使用 new 关键字(在堆上)?

After reading some tutorials I am still unclear on some points about memory management in C++.

1.
when a class declared with the new operator goes out of scope is its destructor called and memory freed?
Is it necessary to call the delete operator to free the class' memory and have its destructor called?

class Test{};

void newTest(){
    Test *t = new Test;
}

int main()
{
    newTest();
    return 0;
}

2.
Are variables (such as a vector) declared with the new keyword freed when the class they reside within is destroyed?
Do those variables have to be explicitly deleted in the class's destructor?

class Test{
    vector<int> *vec;
public:
    Test();
};

Test::Test(){
    *vec = new vector<int>;
}

void newTest(){
    Test t;
}

int main()
{
    newTest();
    return 0;
}

3.
Same as question 2, but with normal variables declared on the stack.
In the following example, is the vector vec deleted when t goes out of scope?

class Test{
    vector<int> vec;
};

void newTest(){
    Test t;
}

int main()
{
    newTest();
    return 0;
}

4.
Finally, which is the better way to declare a vector in a class, normally (on the stack) or with the new keyword (on the heap)?

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

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

发布评论

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

评论(6

东京女 2024-11-26 03:48:12

听起来您可能有 Java 背景,因此 new 在 C++ 中的工作方式有点不同。

  1. new分配的内存必须用delete显式销毁。此示例存在内存泄漏。

  2. 与问题1类似,必须在类析构函数中删除内存才能回收。

  3. 在这种情况下,向量将被自动破坏。

  4. 在类中,总是更喜欢按值存储成员(而不是使用 new ),除非您有特殊原因要这样做。仅仅因为它在类中按值存储并不意味着它在堆栈上,它与包含类占用的内存区域相同。

最后请注意,在 C++ 中,您可以使用 RAII 来使内存管理更不容易出错。例如,看一下shared_ptr、scoped_ptr 和unique_ptr。这些都会在适当的时候自动释放新分配的内存。

It sounds like you may come from a Java background, so things with new work a bit differently in C++.

  1. The memory allocated with new must be explicitly destroyed with delete. This example has a memory leak.

  2. Similar to question 1, you must delete the memory in the class destructor to reclaim it.

  3. In this case the vector will be destructed automatically.

  4. Within a class, always prefer to store members by value (as opposed to with new) unless you have a specific reason to do otherwise. Just because it's stored by value within the class doesn't mean it's on the stack, it's in the same region of memory that the containing class occupies.

Finally note that in C++ you can use RAII to make memory management much less error prone. Take a look at shared_ptr, scoped_ptr, and unique_ptr for example. These all handle automatically freeing the newly allocated memory when appropriate.

标点 2024-11-26 03:48:12
  1. 不,析构函数没有被调用,内存也没有被释放。您必须删除该对象。
  2. 不,变量没有被释放。您必须在析构函数中删除它们。
  3. 是的,vec 被删除(调用析构函数并释放内存)。
  4. 如果可能的话,通常在堆栈上更好。例如,如果将对象的所有权传递给另一个对象,则这可能是不可能的。另外,不应在堆栈上分配太多内存(操作系统对此有限制),在这种情况下,应在堆上分配对象。
  1. No, the destructor is not called and the memory is not freed. you have to delete the object.
  2. No, the variables are not freed. You have to delete them in the destructor.
  3. Yes, vec is deleted (the destructors are called and the memory is freed).
  4. Usually on the stack is better, when possible. It may not be possible if, for example, the ownership of the object is passed to another object. Also, one should not allocate too much memory on the stack (the OS has limits on this), in which case the object should be allocated on the heap.
空气里的味道 2024-11-26 03:48:12
  1. 不会,当指针超出范围时,使用 new 创建的对象不会自动销毁。您需要显式删除任何此类对象。
  2. 同样的答案。任何使用 new 分配的内存都必须显式释放。大多数编写良好的类都会在析构函数中为您执行此操作。如果您正在编写该类,请确保清理该类使用的所有内存。
  3. 该对象会自动为您销毁。而且,如果写得好,它会自动销毁它分配的任何内存。
  4. 大多数类实例应该分配为局部变量,因为这将确保它们被自动清理。但是,如果您全局需要它们或作为类的一部分,则需要适当地声明它们。
  1. No, an object created using new is not automatically destroyed when your pointer goes out of scope. You need to explicitly delete any such object.
  2. Same answer. Any memory allocated with new must be freed explicitly. Most well-written classes will do this for you in the destructor. If you are writing the class, make sure you clean up any memory the class uses.
  3. This object is destroyed automatically for you. And, if it is well written, it will automatically destroy any memory it allocates.
  4. Most class instances should be allocated as local variables since this will ensure they are cleaned up automatically for you. However, if you need them globally or as part of a class, you'll need to declare them appropriately.
恰似旧人归 2024-11-26 03:48:12

您应该更愿意说对象具有动态存储而不是“位于堆上”。同样,使用“自动存储”而不是“在堆栈上”。

前者在标准中实际使用,而后者则更加口语化。

如果一个对象具有自动存储功能,那么当该对象超出范围(在包含块的末尾)时,编译器将自动调用其析构函数。

使用new分配的内存需要显式释放。实际指针的存储将被回收,但它指向的对象不会被回收。

因此,如果您使用new,则需要有一个匹配的deletenew[] 需要与 delete[] 相匹配。

(“智能指针”非常有用,因为它将帮助您不必跟踪newdelete。查找一下!)。

销毁一个向量(如果分配了新的,则通过删除,或者如果是自动,则当它离开范围时)将调用其元素的析构函数。这就是为什么它应该是我们持有多个物体的首选方式。

结论:

如果可能的话尝试使用智能指针或集合。
否则,请确保删除新增的内容。 (如果您编写一个类,请在构造函数中分配任何动态成员并在类的析构函数中删除它们。)

You should prefer to say an object has dynamic storage instead of "being on the heap". Similarly, use "automatic storage" instead of "on the stack".

The former are actually used in the standard, while the latter are more colloquial.

If an object has automatic storage then the compiler will automatically call its destructor when the object goes out of scope (at the end of the containing block).

The memory allocated with new needs to be explicitly released. The storage for the actual pointer will be reclaimed, but not the object it points to.

So, if you use new you need to have a matching delete. A new[] needs to be matched by a delete[].

(A "smart pointer" quite useful, as it will help relieve you of having to keep track of the new and delete's. Look it up!).

Destroying a vector (either via delete if allocated with new, or when it leaves scope if auto) will call the destructor of its elements. This is why it should we the preferred way to held multiple objects.

Conclusion:

If possible try to use smart pointers or collections.
Otherwise, make sure you delete what you new. (And if you write a class, allocate in the constructor any dynamic members and delete them in the class' destructor.)

最笨的告白 2024-11-26 03:48:12
  1. 当使用 new 运算符声明的类超出范围时,是否会调用其析构函数并释放内存?是否有必要调用delete运算符来释放类的内存并调用其析构函数?

首先是一些术语:

变量要么是对象,要么是指针(类不是用新指针声明的)。
对象超出范围时会自动销毁。
指针不会自动删除。

第二,更喜欢对象而不是指针

void newTest()
{
    Test t;  // t created here and automatically destroyed.
}

第三。如果必须创建一个指针。将其放入智能指针中。

void newTest()
{
    std::auto_ptr<Test> t(new Test());  // t created here and automatically destroyed.
                                        // Which will call delete on the contained pointer.
}

回答问题1:

你声明的指针超出了范围,但内存析构函数没有被调用,内存被泄漏。您需要手动执行此操作(或使用我指出的技术之一)。

  1. 当变量所在的类被销毁时,使用 new 关键字声明的变量(例如向量)是否会被释放?这些变量是否必须在类的析构函数中显式删除?

术语

您的意思是用new 初始化的指针,而不是用new 关键字声明

问题2 的答案。

不。您必须在析构函数中手动调用destroy。但类中最好不要有指针。而是在类中声明一个向量对象,然后它将自动销毁。

class Test
{
    vector<int>                   vectorObject;
    std::auto_ptr<vector<int> >   vectorPtrInSmartPointer;
    vector<int>*                  vectorRaw
public:
    Test();
    ~Test();
private:
    Test(Test const& copy);
    Test& operator=(Test const& copy);
};

Test::Test()
   : vectorPtrInSmartPointer(new vector<int>())  // Need to initialize the smart pointer.
   , vectorRaw(new vector<int>)                  // Need to initialize the RAW pointer
{
   // Note the vectorObject was automatically created.
}
Test::~Test()
{
   delete vectorRaw;                             // Need to manually release the RAW pointer.
}
// Smart pointer and object auto released.

笔记:
因为类 Test 包含一个 RAW 指针(向量*),所以我必须手动禁用复制构造函数 Test::Test(Test const&) 和赋值运算符 Test&运算符=(测试常量&)。这是为了确保遵循 3 规则。

  1. 与问题 2 相同,但在堆栈上声明普通变量。在下面的示例中,当 t 超出范围时,向量 vec 是否会被删除?

是的。

  1. 最后,在类中声明向量的更好方法是通常(在堆栈上)还是使用 new 关键字(在堆上)?

将其称为堆栈/堆会掩盖细节(因为成员可能是动态分配对象的自动成员)。更愿意将它们视为自动变量动态变量。当自动变量的包含范围被销毁时,自动变量会被自动销毁。所以对于函数变量来说,这意味着当你离开函数时。对于类成员来说,这意味着对象被销毁。选择是更喜欢使用自动变量(即不使用 new 进行分配)。

  1. when a class declared with the new operator goes out of scope is its destructor called and memory freed? Is it necessary to call the delete operator to free the class' memory and have its destructor called?

First some terminology:

A variable is either an object or a pointer (A clas is not declared with a new pointer).
Objects are automatically destroyed when they go out of scope.
Pointers are NOT deleted automatically.

Second prefer obejcts to pointers

void newTest()
{
    Test t;  // t created here and automatically destroyed.
}

Third. If you must create a pointer. Put it inside a smart pointer.

void newTest()
{
    std::auto_ptr<Test> t(new Test());  // t created here and automatically destroyed.
                                        // Which will call delete on the contained pointer.
}

Answer Question 1:

The pointer you declare goes out of scope but the memory is destructor is not called and the memory is leaked. You would need to do it manually (or use one of the techniques I pointed out).

  1. Are variables (such as a vector) declared with the new keyword freed when the class they reside within is destroyed? Do those variables have to be explicitly deleted in the class's destructor?

Terminology

You mean pointers initialized with new rather then declared with the new keyword

Answer to Question 2.

No. You must manually call destroy in the destructor. But it is better not to have a pointer in the class. Rather declare a vector object inside the class then it will be automatically destroyed.

class Test
{
    vector<int>                   vectorObject;
    std::auto_ptr<vector<int> >   vectorPtrInSmartPointer;
    vector<int>*                  vectorRaw
public:
    Test();
    ~Test();
private:
    Test(Test const& copy);
    Test& operator=(Test const& copy);
};

Test::Test()
   : vectorPtrInSmartPointer(new vector<int>())  // Need to initialize the smart pointer.
   , vectorRaw(new vector<int>)                  // Need to initialize the RAW pointer
{
   // Note the vectorObject was automatically created.
}
Test::~Test()
{
   delete vectorRaw;                             // Need to manually release the RAW pointer.
}
// Smart pointer and object auto released.

Note:
Because the class Test contains a RAW pointer (vector*) I had to manually disable the copy constructor Test::Test(Test const&) and assignment operator Test& operator=(Test const&). This is to make sure the Rule of 3 is being followed.

  1. Same as question 2, but with normal variables declared on the stack. In the following example, is the vector vec deleted when t goes out of scope?

Yes.

  1. Finally, which is the better way to declare a vector in a class, normally (on the stack) or with the new keyword (on the heap)?

Calling it the stack/heap obscures the details (as a member may an automatic member of dynamically allocated object). Prefer to think of them as automatic variablesand dynamic variables. The automatic variables are autoamtically destroyed when their containing scope is destroyed. So for function variables this mean when you leave the function. For class members this means when the object is destroyed. The choice would be to prefer be to use automatic variables (ie not to allocate with new).

极致的悲 2024-11-26 03:48:12

这两个简单的规则应该可以回答所有问题:

  1. 您的代码中的 delete 数量应该与 new 数量一样多。
  2. 尽可能从堆栈而不是堆中分配。

These two simple rules should answer all the questions:

  1. You should have as delete in your code as many as new.
  2. Prefer allocating from stack whenever possible instead of heap.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文