编译器可以进行很多优化(比如内联一些函数),我有点怀疑,在我的程序中的函数调用之后(基于 OS X 的系统监视器),并非所有为局部变量分配的内存都被清除,所以这就是我要问的原因:标准是否保证局部变量的所有析构函数都会在它们超出范围时被准确地调用?
5 回答
是的。根据 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 或其他几个工具(google 用于“内存泄漏检测”)。在这种情况下,您将获得有关分配、释放、泄漏、内存访问违规等的最精确信息。
是的,可以保证每个超出范围的变量都会调用它的析构函数。
6.7 声明声明
2 具有自动存储持续时间(3.7.3)的变量在每次执行其声明语句时都会被初始化。在块中声明的具有自动存储持续时间的变量在退出块时被销毁(6.6)。
是的,这将永远发生。它由 C++ 保证。来自C++ FAQ 精简版:
[11.5] 我应该在局部变量上显式调用析构函数吗?
不!
析构函数将在创建本地的块的 close } 处再次调用。这是语言的保证;它自动发生;没有办法阻止它发生。但是第二次在同一个对象上调用析构函数会得到非常糟糕的结果!砰! 你死定了!
它超出了您的问题,但基础是相同的。
如果你有这样的代码:
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.
}