析构函数不起作用?

3
#include <iostream>

using namespace std;

class Tester {
public:
Tester(int x);
~Tester();
int who;
} Tester_g_1(1) , Tester_g_2(2);

Tester::Tester(int id) {
cout << "Intializing" << id << endl ;
who = id;
}

Tester::~Tester() {
cout << "Destroying" << who << endl;
}

int main() {
Tester localObj(3);
cout << "This is not the first line to be displayed";
    system("pause");
return 0;

}

我得到的输出是:
Intializing1
Intializing2
Intializing3
This is not the first line to be displayedPress any key to continue . . .

为什么析构函数中的语句不起作用? 使用情况: 编译器 - 微软Visual C++ 2010 Express 操作系统 - Win7

1
http://www.parashift.com/c++-faq-lite/dtors.html - user195488
9个回答

10
localObjmain结束后被销毁(因为它的作用域),而这发生在system("pause")之后。你按下一个键,析构函数运行,但立即关闭窗口,所以你看不到它。
要查看析构函数的文本,您必须从命令行运行程序,或使用“Run”菜单中的“Start program without debugging”项(如果我记得正确,这个热键是Ctrl+F5 - 感谢@Cody Gray)。这会在可执行文件终止后添加“按任意键继续”,因此您将能够看到析构函数写入的文本。
另一种查看析构函数运行的方法是将变量封装在较小的范围内,您可以轻松地像这样做:
// ...

int main() {
    {    // the braces create a new scope...
        Tester localObj(3);
        cout<<"Inside the Tester scope..."<<endl;
    }    // ... that ends here
    cout << "... outside the Tester scope!";
    cout<<"Press Enter to exit...";
    cin.ignore();
    return 0;
}

顺便说一下,system("pause")很丑陋且不可移植,应该避免使用。


一个比浏览菜单更简单的方法是按下CTRL+F5。 - Cody Gray
@ Matteo Italia,你能提供一个替代方案吗? - Suhail Gupta
2
例如 cin.ignore()。但是根据我的经验,程序结尾的暂停并不是必须的。如果你在调试器中运行程序,可以在 main 函数的 return 上添加断点;如果你在 VS 中运行程序且没有使用调试器,可以使用 Ctrl+F5;如果你在控制台中运行程序,因为窗口不会关闭,所以你根本不需要这个暂停。 - Matteo Italia
哇,我从来不知道只使用空括号可以如此有用 :) - user2097310

4
析构函数在按任意键继续. . .之后被调用。

4

变量在作用域结束时被销毁。

实际上,它在暂停之后被销毁,所以你可能只是看不到它。

如果你在命令提示符中运行它,你会看到这一行。


3

当您使用 pause 命令时,对象还没有超出其范围,因此其析构函数不会被调用。建议从命令行运行程序以查看完整输出,即可看到析构函数的调用。


2

你的对象还没有超出作用域。你仍在进行系统调用。

你可以使用一对花括号引入新的作用域:

{
   Tester localObj(3);
   cout << "This will be run before the destructor." << endl;
}

或者在命令行提示符中运行程序(运行cmd.exe,然后从提示符开始运行程序),这样您就有足够的时间来查看析构函数的输出。

1

因为你没有销毁对象。只要它在作用域内,析构函数就不会被调用。

尝试使用以下代码:

void someOtherFunction(){
Tester localObj(3);
}

int main() {
someOtherFunction();
cout << "This is not the first line to be displayed";
    system("pause");
return 0;

}

或者您也可以在堆上分配对象(而不是像上面的示例中使用堆栈):

Tester* tester=new Tester(3);
delete tester;

1

在堆栈上创建的对象在超出其作用域时会自动销毁。为了证明这一点,您可以在main()内使用虚拟作用域来处理本地变量:

int main() 
{
   {
      Tester localObj(3);
   }

   cout << "This is not the first line to be displayed";
   system("pause");
   return 0;
}

在堆栈上实例化的全局变量会在main()返回之后(但在销毁std::cout之前)被销毁。


0

很有可能它确实会显示,但你没有足够的时间看到它发生(破坏将在“return 0;”语句期间发生)。

也许如果你把那段代码放进一个函数中,你就能看到localObj的破坏,因为在离开函数后它会超出作用域:

void f(){
    Tester localObj(3);
    cout<<"In local function f";
}

/*...*/ 

int main(){
    f();
    system("pause");
    return 0;
}

0

你的析构函数被调用在

return 0;

之后,因此你没有看到析构函数所做的事情。 但它仍然运行,只是你看不到。

如果你在VStudio中,可以按CTRL+F5,它会在程序终止后添加“按任意键继续”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接