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 docs 说 String
没有堆栈语义的情况下这仍然有效?
堆栈语义是一个纯粹的编译器特性,它在生成的 MSIL 中完全消失了。编译器自动生成所需的 gcnew
来创建 String 对象。并且通常会自动生成 Dispose() 调用,但在这种情况下不会,因为 String 类型没有实现 IDisposable。
您只需要 %
运算符来让编译器满意,它实际上不会生成任何代码。自动生成的字符串对象已经是引用类型了。
所以这两个代码段完全相同,并且生成完全相同的 MSIL。您可以通过使用像 ildasm 这样的反编译器查看它来验证。
喜欢它最易读和最合乎逻辑的版本。这肯定是第一个,在非一次性类型上使用堆栈语义没有意义,只会混淆任何阅读代码的人。但这取决于你。
这两个定义有什么区别:
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 docs 说 String
没有堆栈语义的情况下这仍然有效?
堆栈语义是一个纯粹的编译器特性,它在生成的 MSIL 中完全消失了。编译器自动生成所需的 gcnew
来创建 String 对象。并且通常会自动生成 Dispose() 调用,但在这种情况下不会,因为 String 类型没有实现 IDisposable。
您只需要 %
运算符来让编译器满意,它实际上不会生成任何代码。自动生成的字符串对象已经是引用类型了。
所以这两个代码段完全相同,并且生成完全相同的 MSIL。您可以通过使用像 ildasm 这样的反编译器查看它来验证。
喜欢它最易读和最合乎逻辑的版本。这肯定是第一个,在非一次性类型上使用堆栈语义没有意义,只会混淆任何阅读代码的人。但这取决于你。