"using"关键字用于分配新的C++/CLI类

use*_*240 0 c# memory idisposable c++-cli

我在'C++/CLI'中有一个程序集,它实现了某些类.我们假设该类是'SomeType'.

现在,在'C#'开发的应用程序中,执行以下操作 -

while(!Console.KeyAvailable)
{
   using(SomeType type = new SomeType())
   {
       type.doSomething(); //do something
   }
}
Run Code Online (Sandbox Code Playgroud)

在任何情况下都会有任何后果,例如内存泄漏等,比如是否存在未处理的异常或任何此类情况?

我读到using关键字通常应该用于实现IDisposable的类,但对于C++/CLI类?

Han*_*ant 8

C++/CLI没有using关键字的等价物.它采用了一种不同的方法,一种是本机C++程序员所期望的方法.谁熟悉一种非常常见的C++习惯用法来实现确定性破坏,即RAII模式.调用它需要使用"堆栈语义".运行良好,但语法要求相当模糊.

我将首先展示笨拙的方式,有助于演示语法差异.让我们使用StreamReader,.NET中的一次性类:

String^ ReadTopLineFromFile(String^ path) {
    StreamReader^ reader = gcnew StreamReader(path);
    try {
        return reader->ReadLine();
    }
    finally {
        delete reader;
    }
}
Run Code Online (Sandbox Code Playgroud)

try/finally是使代码异常安全的原因,如果ReadLine()抛出异常,则StreamReader对象仍然被释放,并且保证文件上的锁定被释放.这是C#编译器在您使用该using语句时自动发出的代码.还要注意delete运算符的使用,它实际上调用了StreamReader :: Dispose()方法.编译器不会让你写reader->Dispose(),使用运算符是必需的.

现在是C++/CLI编译器支持的使用版本.您可以通过模拟本机C++编译器处理在堆栈上分配的C++对象的方式来调用堆栈语义.像这样:

String^ ReadTopLineFromFile(String^ path) {
    StreamReader reader(path);
    return reader.ReadLine();
}   // <== disposed here
Run Code Online (Sandbox Code Playgroud)

请注意变量名称上缺少的^ hat,通常在存储引用类型引用时需要.故意省略它是调用模式的原因.无需显式gcnew调用,编译器会自动发出它.另请注意->,您现在不再使用取消引用该对象.

C++/CLI编译器自动生成try/finally块以及delete操作符调用.这是在示波器块的右括号中发出的.就像本机C++编译器一样.虽然看起来托管对象是在堆栈上分配的,但这只是一种语法错觉,它仍然在GC堆上.

语法当然是非常不同的,唯一真正的挂起功能.知道何时使用^ hat以及何时依赖堆栈语义是需要学习的东西,需要一段时间.