C++/CLI 语言详述 8.3---8.6节

Standard ECMA-372 1st Edition / December 2005

C++/CLI Language Specification

C++/CLI 语言详述

译者:Enzo Yang

 

8.3 参数

一个参数数组(parameter array)是一种到以省略号结尾的参数列表的类型安全转换.

一个参数数组以符号开头,紧跟着就是CLI的数组类型.一个函数中只能使用一个参数数组, 而且参数数组必须是最后一个参数. 参数数组只能是单维CLI数组. 函数调用者可以传递一个或任何个数特定同样的变量给参数数组. 下面是例子.

       void F (…array<int>^ args) {

              Console::WriteLine(“# of arguments: {0}”, args->Length);

              for (int i = 0; i < args->Length; i++)

                     Console::WriteLine(“/targs[{0}] =  {1}”, i , args[i]);

       }

       int main() {

              F();

              F(1);

              F(1, 2);

              F(1, 2, 3);

              F(gcnew array<int> {1, 2, 3, 4});

}

这里显示了可以处理不同个数int参数的函数F, 和几个对F的调用, 输出如下.

       # of arguments: 0

       # of arguments: 1

              args[0] = 1

       # of arguments: 2

              args[0] = 1

              args[1] = 2

       #of arguments: 3

              args[0] = 1

              args[1] = 2

              args[2] = 3

       # of arguments: 4

              args[0] = 1

              args[1] = 2

              args[2] = 3

              args[3] = 4

如果把参数数组定义为一个装有System::Object^CLI数组的话, 那么可以向它传递不同类型的参数; 比如说:

       void G (…array<Object^>^ args) { … }

       G(10, “hello”, 1.23, ‘X’);         // arguments 1 , 3 , and 4 are boxed

这本标准中有好多例子都用了Console类的WriteLine函数. 它调用参数的行为就像下面演示的那样

       int a = 1, b = 2;

       Console::WriteLine(“a = {0}, b = {1}”, a , b);

它是用参数数组来实现的. Console类为WriteLine提供了几种重载版本,一部分用来处理那些传来很少参数的情况, 另一部分是用参数数组处理不定个数参数的情况.

       namespace System {

              public ref class Object { … };

              public ref class String { … };

              public ref class Console {

              public:

                     static void WriteLine(String^ s) { … }

                     static void WriteLine(String^ s, Object^ a) { … }

                     static void WriteLine(String^ s, Object^ a, Object^ b) { … }

                     static void WriteLine(String^ s, Object^ a, Object^ b, Object^ c)

                            { … }

                    

                     static void WriteLine(String^ s, …array<Object^>^ args) { … }

              };

       }

CLI库使用C#的语法来显示库里面的函数, C#的关键字params表示一个参数数组. 比如, 上面WriteLine函数的声明用C#写是这样的:

       public static void WriteLine(string s, params object[] args)

 

8.4 自动的内存管理

       public ref class Stack {

       public:

              Staci() {

                     first = nullptr;

              }

              property bool IsEmpty {

                     bool get() {

                            return (first == nullptr);

                     }

              }

              Object^ Pop() {

                     if (first == nullptr)

                            throw gcnew Exception(“Can’t Pop from an empty Stack.”);

                     else {

                            Object^ temp = first->Value;

                            first = first->Next;

                            return temp;

                     }

              }

              void Push(Object^ o) {

                     first = gcnew Node( o , first);

              }

              ref struct Node {

                     Node^ Next;

                     Object^ Value;

                     Node(Object^ value) {

                            Next = nullptr;

                            Value = value;

                     }

                     Node(Object^ value, Node^ next) {

                            Next = next;

                            Value = value;

                     }

              };

       private:

              Node^ first;

       };

这个例子显示了一个用链表实现的Stackl. Node实例是在调用Push函数时创建的, 当不要用时垃圾收集器就会把它回收. 当一个Node实例不再可能被任何代码得到时它就可以被回收了. 比如说, 当一个节点从Stack中清除后, 这个节点就具备了被回收的条件.

       int main() {

              Stack^ s = gcnew Stack;

              for (int i = 0 ; i < 10; i++)

                     s->push(i);

              s = nullptr;

       }

这个例子展示了一段使用Stack类的代码. 这个Stack在被创建之初压入了10个元素, 然后把它的句柄赋值为nullptr. 一旦变量s被设置为空值, 这个Stack连同那十个Node都具备了被回收的条件. 垃圾收集器可以马上把垃圾清除,但没有必要马上.

 

C++/CLI的垃圾收集器可以移动CLI堆中的objects, 但是这是让大多数开发者都看不到的. 对于开发者来说自动的内存管理已经足够了, 但是有时需要控制它来提高一点点性能, C++/CLI提供一个钉住(pin)objectCLI堆中的功能, 通过这样来暂时防止垃圾收集器移动那个object.

       void f(int* p) { *p = 100;}

       int main() {

              array<int>^ arr = gcnew array<int>(100);

              pin_ptr<int> pinp = &arr[0];        //pin arr’s location

              f(pinp);                                       //change arr[0]’s value

       }

 

8.5 表达式

C++/CLI加强了标准C++操作符方面功能. 比如:

# 新增的delegate需要用函数的方式来调用封装在delegate中的函数 (:delegate的解释在后面,现在只要知道它装有一组同样形式的函数,并可以对它里面的函数同时调用就行.)

       # 添加了typeid的用途. 比如说, Int32::typeid返回一个指向System::Type对象的句柄, 这个对象描述了CLIInt32类型.

       # 加强了转换操作符来适应句柄类型.

       # 添加了safe_cast操作符.

       # 添加了操作符gcnew. 它用来分配CLI堆中的内存.

       # 加强了 + - 操作符来分别实现delegate的添加和删除.

       # 加强了简单赋值操作来适应左边运算域是propertyevent的情况.

# 复合赋值操作符被综合到对应的位运算符.(Compoound assignment operators are synthesized from the corresponding binary operator)

 

8.6 语句

新增了for each语句. 这个语句迭代一个集合中的元素, 先后对集合里面的元素执行一个程序块中的代码.

       void dispay(array<int>^ args) {

              for each ( int i in args)

                     Console::WriteLine(i);

       }

一个类如果它实现了System::Collection::IEnumerable接口或者通过一些规则实现了一集合样式(collection pattern), 那么它就可以称为集合类型(collection type).

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值