CLR 数组的声明
更新:2007 年 11 月
从 C++ 托管扩展到 Visual C++ 2008,声明、实例化和初始化托管数组的语法发生了更改。
托管扩展中 CLR 数组对象的声明是标准数组声明的扩展,其中 __gc 关键字被放置在数组对象名及其可能用逗号填充的维数之间,如以下两个示例所示:
void PrintValues( Object* myArr __gc[]);
void PrintValues( int myArr __gc[,,]);
这在新语法中已简化,在新语法中我们使用与 STL vector 声明相似的类似于模板的声明。第一个参数指示元素类型。第二个参数指定数组维数(默认值为 1,所以只有多维数组需要第二个变量)。数组对象本身是一个跟踪句柄,所以必须为其赋予一个插入符号。如果元素类型也是引用类型,则它还需要一个帽子。例如,上面的示例在新的语法中的表示如下:
void PrintValues( array<Object^>^ myArr );
void PrintValues( array<int,3>^ myArr );
由于引用类型是一个跟踪句柄而不是对象,可以将 CLR 数组指定为函数的返回类型。(相反,不能将本机数组指定为函数的返回类型。) 在托管扩展中执行此操作的语法有不太直观。例如:
Int32 f() [];
int GetArray() __gc[];
在 Visual C++ 2008 中,该声明简单很多。例如,
array<Int32>^ f();
array<int>^ GetArray();
两种版本的语言中都支持局部托管数组的简短初始化。例如:
int GetArray() __gc[] {
int a1 __gc[] = { 1, 2, 3, 4, 5 };
Object* myObjArray __gc[] = {
__box(26), __box(27), __box(28), __box(29), __box(30)
};
return a1;
}
在新的语法中得到了显著地简化(请注意,由于在新的语法中装箱是隐式的,所以取消了 __box 运算符 — 有关讨论,请参见 值类型及其行为):
array<int>^ GetArray() {
array<int>^ a1 = {1,2,3,4,5};
array<Object^>^ myObjArray = {26,27,28,29,30};
return a1;
}
由于数组是 CLR 引用类型,所以每个数组对象的声明都是一个跟踪句柄。因此,数组对象必须在 CLR 堆上分配。(简短的表示法隐藏托管的堆分配。) 以下代码是托管扩展下数组对象初始化的显式形式:
Object* myArray[] = new Object*[2];
String* myMat[,] = new String*[4,4];
在新语法中,new 表达式由 gcnew 替换。维数大小作为参数传递给了 gcnew 表达式,如下所示:
array<Object^>^ myArray = gcnew array<Object^>(2);
array<String^,2>^ myMat = gcnew array<String^,2>(4,4);
在新的语法中,显式初始化列表可以遵循 gcnew 表达式;托管扩展中不支持此功能。例如:
// explicit initialization list following gcnew
// was not supported in Managed Extensions
array<Object^>^ myArray =
gcnew array<Object^>(4){ 1, 1, 2, 3 };