C++11 为什么这里显式调用析构函数?
在浏览一些与通过SMTP发送电子邮件相关的代码时,我在MSDN中得到了以下代码片段C++11 为什么这里显式调用析构函数?,c++11,c++-cli,destructor,C++11,C++ Cli,Destructor,在浏览一些与通过SMTP发送电子邮件相关的代码时,我在MSDN中得到了以下代码片段 static void CreateMessageWithAttachment( String^ server ) { String^ file = L"data.xls"; MailMessage^ message = gcnew MailMessage( L"jane@contoso.com",L"ben@contoso.com",L"Quarterly data report.",L"See
static void CreateMessageWithAttachment( String^ server )
{
String^ file = L"data.xls";
MailMessage^ message = gcnew MailMessage( L"jane@contoso.com",L"ben@contoso.com",L"Quarterly data report.",L"See the attached spreadsheet." );
Attachment^ data = gcnew Attachment(file, MediaTypeNames::Application::Octet);
ContentDisposition^ disposition = data->ContentDisposition;
disposition->CreationDate = System::IO::File::GetCreationTime( file );
disposition->ModificationDate = System::IO::File::GetLastWriteTime( file );
disposition->ReadDate = System::IO::File::GetLastAccessTime( file );
message->Attachments->Add( data );
SmtpClient^ client = gcnew SmtpClient( server );
client->Credentials = CredentialCache::DefaultNetworkCredentials;
client->Send( message );
data->~Attachment();
client->~SmtpClient();
}
我只是想知道他们为什么在这里叫析构函数?我是不是遗漏了什么
data->~Attachment();
client->~SmtpClient();
在C++/CLI中,
ref
类析构函数是对
以下C++/CLI类在编译时:
public ref类测试
{
公众:
Test(){System::Console::WriteLine(“ctor”);}
~Test(){System::Console::WriteLine(“dtor”);}
静态void Foo()
{
auto foo=gcnew Test();
foo->~Test();
}
};
反编译到以下C#代码(C#语义更接近底层IL代码,因此这是可视化发生的情况的好方法):
公共类测试:IDisposable
{
公开考试()
{
控制台写入线(“ctor”);
}
私有void~Test()
{
控制台写入线(“dtor”);
}
公共静态void Foo()
{
新测试().Dispose();
}
受保护的虚拟void Dispose([Marshallas(UnmanagedType.U1)]bool A_0)
{
如果(A_0)
{
这个。~Test();
}
其他的
{
这个.Finalize();
}
}
公共虚拟void Dispose()
{
这个。处置(真实);
GC.SuppressFinalize((对象)this);
}
}
您可以看到dispose模式是由编译器自动实现的
~Test
“析构函数”被编译为私有方法,并为您生成IDisposable::Dispose
的实现。出于某种原因,编译器还调用(空)终结器
另外,正如您在静态Foo
方法中看到的,Foo->~Test()
被简单地转换为调用Dispose
。编译器不允许您调用foo->Dispose()代码>直接
但是调用“析构函数”(因此是Dispose
方法)的标准方法是使用delete
关键字:delete foo
与foo->~Test()相同当foo
是托管句柄时,C++/CLI中的code>
请注意,在本例中,不要编写:
auto-foo=gcnew-CppCli::Test();
foo->Whatever();
删除foo;
您可以使用堆栈语义并编写:
testfoo;
foo.Whatever();
foo.~Test()当代码> FoO超出范围时,将调用代码>,如在常规C++中。
为了完整起见,下面是整个过程如何与终结器交互。让我们添加一个:
public ref类测试
{
公众:
Test(){System::Console::WriteLine(“ctor”);}
~Test(){System::Console::WriteLine(“dtor”);}
!Test(){System::Console::WriteLine(“终结器”);}
};
这将反编译为以下类似C的代码:
公共类测试:IDisposable
{
公开考试()
{
控制台写入线(“ctor”);
}
//这是真正的终结器
~Test()
{
本.处置(假);
}
//这就是C++/CLI编译~Test的目的
//让我们称之为方法A
私有void~Test()
{
控制台写入线(“dtor”);
}
//这是C++/CLI编译的!Test
//让我们称之为方法B
私有void!Test()
{
控制台写入线(“终结器”);
}
[HandleProcessCorruptedStateExceptions]
受保护的虚拟void Dispose([Marshallas(UnmanagedType.U1)]bool A_0)
{
如果(A_0)
{
这是.~Test();//MethodA,不是终结器
}
其他的
{
尝试
{
此。!Test();//方法B
}
最后
{
base.Finalize();
}
}
}
公共虚拟void Dispose()
{
这个。处置(真实);
GC.SuppressFinalize((对象)this);
}
}
请注意,为了增加混淆,在C#中,终结器是~Test()
,它不同于C++/CLI编译器为析构函数生成的private void~Test()
函数。非常感谢您的详细解释,非常有用。您可能还应该注意到~Test()
语法不是标准的。处理托管对象的规范方法是使用<代码>删除>代码>,与一个C++对象相同。@ DavidYaw OOP,你说得对,这是一个重要的点,谢谢!DavidYaw是的,这肯定不会那么令人困惑:)