cpp*_*ame 20 c++ destructor runtime
我想知道C++运行时系统如何检测对象何时超出范围,以便它相应地调用析构函数以释放占用的内存.
谢谢.
Eri*_*rik 25
运行时不会 - 编译器会对范围进行标记并生成调用析构函数的代码.如果您创建一个简单的测试应用程序并查看生成的反汇编,您将看到显式的析构函数调用.
来自MSVC的反汇编代码片段:
int main() {
std::string s1;
...
00971416 call dword ptr [__imp_std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (979290h)]
...
{
std::string s2;
00971440 call dword ptr [__imp_std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (979290h)]
...
}
00971452 call dword ptr [__imp_std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (979294h)]
...
}
0097146B call dword ptr [__imp_std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (979294h)]
Run Code Online (Sandbox Code Playgroud)
Joh*_*itb 18
这在编译时是静态知道的
{
string s; /* ctor called here */
} /* dtor called here */
Run Code Online (Sandbox Code Playgroud)
有时,它更难
{
again:
{
string s; /* ctor called here */
goto again; /* now dtor of s is called here */
string q; /* ctor not called. not reached. */
} /* dtor of s and q would be called here. but not reached */
}
Run Code Online (Sandbox Code Playgroud)
范围以范围结束.它没有"检测"它,编译器以及时调用析构函数的方式编写代码.
例如以下代码
if(something)
{
MyClass test;
test.doSomething();
}
Run Code Online (Sandbox Code Playgroud)
会导致机器代码执行以下操作:
"调用析构函数"和"释放与变量相关的内存"完全是两件不同的事情.
析构函数只是一个函数,当你的对象超出范围或被明确删除时,C++足以为你调用.正如其他人所说,编译器为您生成了这个.它是一种方便的方法,可以清理班级中需要清理的任何内容.
释放与堆栈中的内容相关联的内存涉及了解堆栈如何操作.调用函数时,只需将堆栈上的变量所需的数据量压入堆栈,即可为堆栈中的所有内容分配内存.虽然在C++规范中没有明确说明,但"推"实际上只是让指向堆栈顶部的指针更高(或更低),以便为额外变量腾出空间.这是简单的指针添加.函数返回时,发生指针减法.
void foo()
{
HerClass y;
YourClass x; // stack incremented sizeof(YourClass) + sizeof(HerClass)
return; // destructor called,
// then stack decremented sizeof(YourClass) + sizeof(HerClass)
}
Run Code Online (Sandbox Code Playgroud)
一切都从堆栈中弹出.您可以通过阅读有关调用约定的内容来了解更多信息.
堆内存由程序明确手动控制.除非代码为您执行显式堆管理,否则您需要确保删除新的所有内容.