.net Winform析构函数被调用两次

.net Winform析构函数被调用两次,.net,winforms,c++-cli,destructor,.net,Winforms,C++ Cli,Destructor,我有一个标准的c++cli win32 winform应用程序,它是从VS2013模板生成的 第一个调用返回不可调试的位置“C:\Windows\SysWOW64\user32.dll” 第二个在Application::Run(%instance)之后返回在Main()中: 我不认为这有什么害处,但我很想知道为什么会这样 winforms c++cli对象的工作方式是否固有这种行为?我怎么才能知道是什么引起的 我遵循了这个指南: 这就是原因。UserClass是一种引用类型,您通常会声明一个变

我有一个标准的c++cli win32 winform应用程序,它是从VS2013模板生成的

第一个调用返回不可调试的位置
“C:\Windows\SysWOW64\user32.dll”

第二个在
Application::Run(%instance)之后返回
Main()
中:

我不认为这有什么害处,但我很想知道为什么会这样

winforms c++cli对象的工作方式是否固有这种行为?我怎么才能知道是什么引起的

我遵循了这个指南:

这就是原因。UserClass是一种引用类型,您通常会声明一个变量来存储对带有^hat的对象的引用。但是你没有,你现在调用了一个叫做。它模拟了本地C++中的RAII模式,编译器自动在关闭括号中向析构函数发出调用。 这不适用于从窗体或控件派生的类。这样的对象已经被自动释放,它发生在窗口关闭之后。因此,您会看到对析构函数的两个调用,第一个来自Winforms,第二个来自Main()函数中的隐藏析构函数调用

这实际上不是托管代码中的错误,事实上在某些类中很常见。例如,在派生自流的类上,这几乎是不可避免的。请记住,它是扮演与本地C++析构函数等价的角色的终结器,<代码>!C++/CLI语法中的classname
。尽管如此,如果你不指望它,你的腿很容易被射下来

只需正确编写代码:

ProjectName::UserClass^ instance = gcnew ProjectName::UserClass;
Application::Run(instance);

这就是原因。UserClass是一种引用类型,您通常会声明一个变量来存储对带有^hat的对象的引用。但是你没有,你现在调用了一个叫做。它模拟了本地C++中的RAII模式,编译器自动在关闭括号中向析构函数发出调用。 这不适用于从窗体或控件派生的类。这样的对象已经被自动释放,它发生在窗口关闭之后。因此,您会看到对析构函数的两个调用,第一个来自Winforms,第二个来自Main()函数中的隐藏析构函数调用

这实际上不是托管代码中的错误,事实上在某些类中很常见。例如,在派生自流的类上,这几乎是不可避免的。请记住,它是扮演与本地C++析构函数等价的角色的终结器,<代码>!C++/CLI语法中的classname。尽管如此,如果你不指望它,你的腿很容易被射下来

只需正确编写代码:

ProjectName::UserClass^ instance = gcnew ProjectName::UserClass;
Application::Run(instance);


现在说得通了,漂亮。现在说得通了,漂亮。
ProjectName::UserClass^ instance = gcnew ProjectName::UserClass;
Application::Run(instance);
auto instance = gcnew ProjectName::UserClass;
Application::Run(instance);
Application::Run(gcnew ProjectName::UserClass);