一些涉及类析构函数和删除运算符的内存管理问题?
在阅读了一些教程后,我仍然不清楚 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
听起来您可能有 Java 背景,因此
new
在 C++ 中的工作方式有点不同。用
new
分配的内存必须用delete
显式销毁。此示例存在内存泄漏。与问题1类似,必须在类析构函数中删除内存才能回收。
在这种情况下,向量将被自动破坏。
在类中,总是更喜欢按值存储成员(而不是使用 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++.The memory allocated with
new
must be explicitly destroyed withdelete
. This example has a memory leak.Similar to question 1, you must delete the memory in the class destructor to reclaim it.
In this case the vector will be destructed automatically.
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
new
ly allocated memory when appropriate.删除
该对象。delete
the object.删除
任何此类对象。new
分配的内存都必须显式释放。大多数编写良好的类都会在析构函数中为您执行此操作。如果您正在编写该类,请确保清理该类使用的所有内存。new
is not automatically destroyed when your pointer goes out of scope. You need to explicitlydelete
any such object.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.您应该更愿意说对象具有动态存储而不是“位于堆上”。同样,使用“自动存储”而不是“在堆栈上”。
前者在标准中实际使用,而后者则更加口语化。
如果一个对象具有自动存储功能,那么当该对象超出范围(在包含块的末尾)时,编译器将自动调用其析构函数。
使用
new
分配的内存需要显式释放。实际指针的存储将被回收,但它指向的对象不会被回收。因此,如果您使用
new
,则需要有一个匹配的delete
。new[]
需要与delete[]
相匹配。(“智能指针”非常有用,因为它将帮助您不必跟踪
new
和delete
。查找一下!)。销毁一个向量(如果分配了新的,则通过删除,或者如果是自动,则当它离开范围时)将调用其元素的析构函数。这就是为什么它应该是我们持有多个物体的首选方式。
结论:
如果可能的话尝试使用智能指针或集合。
否则,请确保
删除
您新增
的内容。 (如果您编写一个类,请在构造函数中分配任何动态成员并在类的析构函数中删除它们。)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 matchingdelete
. Anew[]
needs to be matched by adelete[]
.(A "smart pointer" quite useful, as it will help relieve you of having to keep track of the
new
anddelete
'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 younew
. (And if you write a class, allocate in the constructor any dynamic members and delete them in the class' destructor.)首先是一些术语:
变量要么是对象,要么是指针(类不是用新指针声明的)。
对象超出范围时会自动销毁。
指针不会自动删除。
第二,更喜欢对象而不是指针
第三。如果必须创建一个指针。将其放入智能指针中。
回答问题1:
你声明的指针超出了范围,但内存析构函数没有被调用,内存被泄漏。您需要手动执行此操作(或使用我指出的技术之一)。
术语
您的意思是
用new 初始化的指针
,而不是用new 关键字声明
问题2 的答案。
不。您必须在析构函数中手动调用destroy。但类中最好不要有指针。而是在类中声明一个向量对象,然后它将自动销毁。
笔记:
因为类 Test 包含一个 RAW 指针(向量*),所以我必须手动禁用复制构造函数
Test::Test(Test const&)
和赋值运算符Test&运算符=(测试常量&)
。这是为了确保遵循 3 规则。是的。
将其称为堆栈/堆会掩盖细节(因为成员可能是动态分配对象的自动成员)。更愿意将它们视为
自动变量
和动态变量
。当自动变量
的包含范围被销毁时,自动变量会被自动销毁。所以对于函数变量来说,这意味着当你离开函数时。对于类成员来说,这意味着对象被销毁。选择是更喜欢使用自动变量(即不使用 new 进行分配)。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
Third. If you must create a pointer. Put it inside a smart 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).
Terminology
You mean
pointers initialized with new
rather thendeclared 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.
Note:
Because the class Test contains a RAW pointer (vector*) I had to manually disable the copy constructor
Test::Test(Test const&)
and assignment operatorTest& operator=(Test const&)
. This is to make sure the Rule of 3 is being followed.Yes.
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 variables
anddynamic variables
. Theautomatic 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 useautomatic variables
(ie not to allocate with new).这两个简单的规则应该可以回答所有问题:
delete
数量应该与new
数量一样多。These two simple rules should answer all the questions:
delete
in your code as many asnew
.