C++ 我如何调用类的析构函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4036394/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I call the class's destructor?
提问by user261002
I have a simple C++ code, but I don't know how to use the destructor:
我有一个简单的 C++ 代码,但我不知道如何使用析构函数:
class date {
public:
int day;
date(int m)
{
day =m;
}
~date(){
cout << "I wish you have entered the year \n" << day;
}
};
int main()
{
date ob2(12);
ob2.~date();
cout << ob2.day;
return 0;
}
The question that I have is, what should I write in my destructor code, that after calling the destructor, it will delete the day
variable?
我的问题是,我应该在析构函数代码中写什么,在调用析构函数后,它将删除day
变量?
采纳答案by Marius
You should not call your destructor explicitly.
您不应显式调用析构函数。
When you create your object on the stack (like you did) all you need is:
当您在堆栈上创建对象时(就像您所做的那样),您只需要:
int main()
{
date ob2(12);
// ob2.day holds 12
return 0; // ob2's destructor will get called here, after which it's memory is freed
}
When you create your object on the heap, you kinda need to delete
your class before its destructor is called and memory is freed:
当您在堆上创建对象时,您需要delete
在类的析构函数被调用并释放内存之前创建类:
int main()
{
date* ob2 = new date(12);
// ob2->day holds 12
delete ob2; // ob2's destructor will get called here, after which it's memory is freed
return 0; // ob2 is invalid at this point.
}
(Failing to call delete on this last example will result in memory loss.)
(未能在最后一个示例中调用 delete 将导致内存丢失。)
Both ways have their advantages and disadvantages. The stack way is VERY fast with allocating the memory the object will occupy and you do not need to explicitly delete it, but the stack has limited space and you cannot move those objects around easily, fast and cleanly.
这两种方式都有其优点和缺点。堆栈方式分配对象将占用的内存非常快,您不需要明确删除它,但堆栈空间有限,您无法轻松、快速和干净地移动这些对象。
The heap is the preferred way of doing it, but when it comes to performance it is slow to allocate and you have to deal with pointers. But you have much more flexibility with what you do with your object, it's way faster to work with pointers further and you have more control over the object's lifetime.
堆是首选的方法,但在性能方面,分配速度很慢,您必须处理指针。但是您可以更灵活地处理对象,进一步使用指针会更快,并且您可以更好地控制对象的生命周期。
回答by James McNellis
Rarely do you ever need to call the destructor explicitly. Instead, the destructor is called when an object is destroyed.
您很少需要显式调用析构函数。相反,在销毁对象时调用析构函数。
For an object like ob2
that is a local variable, it is destroyed when it goes out of scope:
对于像ob2
这样的对象是局部变量,当它超出范围时会被销毁:
int main()
{
date ob2(12);
} // ob2.~date() is called here, automatically!
If you dynamically allocate an object using new
, its destructor is called when the object is destroyed using delete
. If you have a static object, its destructor is called when the program terminates (if the program terminates normally).
如果您使用 动态分配对象new
,则在使用销毁对象时调用其析构函数delete
。如果你有一个静态对象,它的析构函数会在程序终止时调用(如果程序正常终止)。
Unless you create something dynamically using new
, you don't need to do anything explicit to clean it up (so, for example, when ob2
is destroyed, all of its member variables, including day
, are destroyed). If you create something dynamically, you need to ensure it gets destroyed when you are done with it; the best practice is to use what is called a "smart pointer" to ensure this cleanup is handled automatically.
除非您使用 动态创建某些内容new
,否则您无需执行任何明确的操作来清理它(例如,当ob2
被销毁时,它的所有成员变量,包括day
,都会被销毁)。如果你动态地创建一些东西,你需要确保它在你完成后被销毁;最佳实践是使用所谓的“智能指针”来确保自动处理此清理。
回答by Konrad Rudolph
You do not need to call the destructor explicitly. This is done automatically at the end of the scope of the object ob2
, i.e. at the end of the main
function.
您不需要显式调用析构函数。这是在对象作用域的末尾自动完成的ob2
,即在main
函数的末尾。
Furthermore, since the object has automatic storage, its storage doesn't have to be deleted. This, too, is done automatically at the end of the function.
此外,由于对象具有自动存储,因此不必删除其存储。这也是在函数结束时自动完成的。
Calling destructors manually is almost never needed (only in low-level library code) and deleting memory manually is only needed (and only a valid operation) when the memory was previously acquired using new
(when you're working with pointers).
几乎从不需要手动调用析构函数(仅在低级库代码中),并且仅在先前使用new
(使用指针时)获取内存时才需要手动删除内存(并且仅是有效操作)。
Since manual memory management is prone to leaks, modern C++ code tries not to use new
and delete
explicitly at all. When it's really necessary to use new
, then a so-called “smart pointer” is used instead of a regular pointer.
由于手动内存管理容易泄漏,现代 C++ 代码尽量不使用new
和delete
显式。当确实需要使用时new
,就会使用所谓的“智能指针”而不是常规指针。
回答by David Rodríguez - dribeas
Only in very specific circumstances you need to call the destructor directly. By default the destructor will be called by the system when you create a variable of automatic storage and it falls out of scope or when a an object dynamically allocated with new
is destroyed with delete
.
只有在非常特殊的情况下,您才需要直接调用析构函数。默认情况下,当您创建自动存储的变量并且它超出范围或动态分配的对象new
被销毁时,系统将调用析构函数delete
。
struct test {
test( int value ) : value( value ) {}
~test() { std::cout << "~test: " << value << std::endl; }
int value;
};
int main()
{
test t(1);
test *d = new t(2);
delete d; // prints: ~test: 2
} // prints: ~test: 1 (t falls out of scope)
For completeness, (this should not be used in general) the syntax to call the destructor is similar to a method. After the destructor is run, the memory is no longer an object of that type (should be handled as raw memory):
为了完整起见,(通常不应使用)调用析构函数的语法类似于方法。析构函数运行后,内存不再是该类型的对象(应作为原始内存处理):
int main()
{
test t( 1 );
t.~test(); // prints: ~test: 1
// after this instruction 't' is no longer a 'test' object
new (&t) test(2); // recreate a new test object in place
} // test falls out of scope, prints: ~test: 2
Note: after calling the destructor on t
, that memory location is no longer a test
, that is the reason for recreationof the object by means of the placement new.
注意:在 上调用析构函数后t
,该内存位置不再是 a test
,这就是通过放置 new重新创建对象的原因。
回答by J. Polfer
Even though the destructor seems like something you need to call to get rid of or "destroy" your object when you are done using it, you aren't supposed to use it that way.
尽管析构函数看起来像是在使用完对象后需要调用以摆脱或“销毁”对象的东西,但您不应该那样使用它。
The destructor is something that is automatically called when your object goes out of scope, that is, when the computer leaves the "curly braces" that you instantiated your object in. In this case, when you leave main(). You don't want to call it yourself.
析构函数是当您的对象超出范围时自动调用的东西,也就是说,当计算机离开您实例化对象的“花括号”时。在这种情况下,当您离开 main() 时。你不想自己调用它。
回答by David Thornley
You may be confused by undefined behavior here. The C++ standard has no rules as to what happens if you use an object after its destructor has been run, as that's undefined behavior, and therefore the implementation can do anything it likes. Typically, compiler designers don't do anything special for undefined behavior, and so what happens is an artifact of what other design decisions were made. (This can cause really weird results sometimes.)
您可能会对此处未定义的行为感到困惑。C++ 标准没有关于在对象的析构函数运行后使用它会发生什么的规则,因为这是未定义的行为,因此实现可以做任何它喜欢的事情。通常,编译器设计者不会为未定义的行为做任何特别的事情,因此发生的事情是其他设计决策的产物。(这有时会导致非常奇怪的结果。)
Therefore, once you've run the destructor, the compiler has no further obligation regarding that object. If you don't refer to it again, it doesn't matter. If you do refer to it, that's undefined behavior, and from the Standard's point of view the behavior doesn't matter, and since the Standard says nothing most compiler designers will not worry about what the program does.
因此,一旦您运行了析构函数,编译器就没有关于该对象的进一步义务。如果你不再提及它,那也无所谓。如果你确实引用了它,那是未定义的行为,从标准的角度来看,行为无关紧要,而且由于标准没有说什么,大多数编译器设计者不会担心程序做什么。
In this case, the easiest thing to do is to leave the object untouched, since it isn't holding on to resources, and its storage was allocated as part of starting up the function and will not be reclaimed until the function exits. Therefore, the value of the data member will remain the same. The natural thing for the compiler to do when it reads ob2.day
is to access the memory location.
在这种情况下,最简单的做法是保持对象不变,因为它没有占用资源,并且它的存储是作为启动函数的一部分分配的,并且在函数退出之前不会被回收。因此,数据成员的值将保持不变。编译器在读取时要做的自然事情ob2.day
是访问内存位置。
Like any other example of undefined behavior, the results could change under any change in circumstances, but in this case they probably won't. It would be nice if compilers would catch more cases of undefined behavior and issue diagnostics, but it isn't possible for compilers to detect all undefined behavior (some occurs at runtime) and often they don't check for behavior they don't think likely.
与未定义行为的任何其他示例一样,结果可能会随着环境的任何变化而改变,但在这种情况下,它们可能不会。如果编译器能够捕获更多未定义行为的情况并发出诊断信息,那就太好了,但是编译器不可能检测到所有未定义的行为(有些发生在运行时),而且它们通常不会检查他们不认为的行为可能。
回答by Doug Beleznay
In this case your destructor does not need to delete the day variable.
在这种情况下,您的析构函数不需要删除 day 变量。
You only need to call delete on memory that you have allocated with new.
你只需要在你用 new 分配的内存上调用 delete 。
Here's how your code would look if you were using new and delete to trigger invoking the destructor
如果您使用 new 和 delete 来触发调用析构函数,则代码如下所示
class date {
public: int* day;
date(int m) {
day = new int;
*day = m;
}
~date(){
delete day;
cout << "now the destructor get's called explicitly";
}
};
int main() {
date *ob2 = new date(12);
delete ob2;
return 0;
}