C++运行时系统如何知道对象何时超出范围

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)


Ben*_*igt 6

它与运行时无关.编译器跟踪每个词法变量的范围,并添加析构函数调用.


Mar*_*rio 5

范围以范围结束.它没有"检测"它,编译器以及时调用析构函数的方式编写代码.

例如以下代码

if(something)
{
    MyClass test;
    test.doSomething();
}
Run Code Online (Sandbox Code Playgroud)

会导致机器代码执行以下操作:

  • 评估跳跃
  • 如果需要跳下来
  • 分配内存进行测试
  • 在测试时调用MyClass的构造函数
  • 在测试时调用doSomething
  • 在测试中调用MyClass的析构函数
  • 释放记忆


Dou*_* T. 5

"调用析构函数"和"释放与变量相关的内存"完全是两件不同的事情.

析构函数只是一个函数,当你的对象超出范围或被明确删除时,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)

一切都从堆栈中弹出.您可以通过阅读有关调用约定的内容来了解​​更多信息.

堆内存由程序明确手动控制.除非代码为您执行显式堆管理,否则您需要确保删除新的所有内容.