编译器可以进行很多优化(比如内联一些函数),我有点怀疑在我的程序中,所有为局部变量分配的内存是否在函数调用后都被清除了(基于OS X系统监视器的结果)。因此我想问:标准是否保证所有局部变量的析构函数会在它们超出作用域的那一刻被精确调用?
编译器可以进行很多优化(比如内联一些函数),我有点怀疑在我的程序中,所有为局部变量分配的内存是否在函数调用后都被清除了(基于OS X系统监视器的结果)。因此我想问:标准是否保证所有局部变量的析构函数会在它们超出作用域的那一刻被精确调用?
是的。根据C++11标准第3.7.3段:
在块作用域中显式声明为
register
或未显式声明为static
或extern
的变量具有自动存储期。这些实体的存储持续到创建它们的块退出为止。
请注意,这仅涉及具有自动存储期的变量。如果您使用new
动态创建对象并将结果分配给本地原始指针,则仅会销毁原始指针,而不是指向的对象:
{
int* foo = new int(42);
} // Here you have a memory leak: the foo pointer is destroyed,
// but not the object foo pointed to
是的,这是有保证的。
使用系统监视器来监控内存使用可能不太准确,因为应用程序不会将内存返回给系统。一旦分配,它就属于应用程序,即使您的对象被销毁,您也可能看不到任何区别。
如果您想保证您的应用程序没有内存泄漏,您可能需要使用诸如valgrind或Google的drMemory等工具,或者其他几个(搜索"memory leak detection")。在这种情况下,您将获得关于分配、释放、泄漏、内存访问违规等方面最精确的信息。
每个超出作用域的变量都会保证调用其析构函数。
2 具有自动存储期(3.7.3)的变量在其声明语句执行时每次都会被初始化。在块中声明的具有自动存储期的变量在退出该块时被销毁(6.6)。
如果您的代码类似于以下内容,它将会起作用:
void f()
{
A a; // create a local instance of A
// memory will be allocated on the stack,
// and the constructor for `a` will be called.
// various code here
// here at the end of the scope,
// the destructor for `a` will be called,
// and the memory on the stack will be freed.
}
[11.5] 我应该在局部变量上显式调用析构函数吗?
不需要!
析构函数将在创建局部变量的块的关闭}处再次调用。这是语言的保证;它会自动发生;无法阻止它发生。但是,如果在同一对象上第二次调用析构函数,可能会导致非常糟糕的结果!崩溃!你死定了!
虽然有些超出了你的问题,但基本原理是相同的。