C++/Cli 堆栈语义和跟踪引用运算符

C++/Cli Stack Semantics and Tracking-Reference Operator

这两个定义有什么区别:

using namespace System;

String^ ToStringA(char* str)
{
    return gcnew String(str);
}

String^ ToStringB(char* str)
{
    return %String(str);
}

我的猜测是,在后者中,System::String 是使用 "stack semantics" 到 return 创建的 %-operator 对该对象的引用,所以它确实如此与前者完全相同。真的吗?有什么微妙之处吗?

gcnew-方式在这里可能更清晰,因此首选,但以下情况如何:

String^ ToString2A(char* str1, char* str2)
{
    return gcnew String(str1) + gcnew String(str2);
}

String^ ToString2B(char* str1, char* str2)
{
    return %String(str1) + %String(str2);
}

可以进行任何其他处理,而不仅仅是串联。有什么理由不使用 %?

额外的问题:为什么在 the docsString 没有堆栈语义的情况下这仍然有效?

堆栈语义是一个纯粹的编译器特性,它在生成的 MSIL 中完全消失了。编译器自动生成所需的 gcnew 来创建 String 对象。并且通常会自动生成 Dispose() 调用,但在这种情况下不会,因为 String 类型没有实现 IDisposable。

您只需要 % 运算符来让编译器满意,它实际上不会生成任何代码。自动生成的字符串对象已经是引用类型了。

所以这两个代码段完全相同,并且生成完全相同的 MSIL。您可以通过使用像 ildasm 这样的反编译器查看它来验证。

喜欢它最易读和最合乎逻辑的版本。这肯定是第一个,在非一次性类型上使用堆栈语义没有意义,只会混淆任何阅读代码的人。但这取决于你。