C++/CLI中栈工具的设计问题
C++/CLI中新推出的自动确定性资源接纳(Automatic deterministic destruction)被视 为一个优秀的设计。是利用所谓C++/CLI这个“新瓶”来装Bjarne Stroustrup提 出的RAII这个“旧酒”。
这简直不错,相对而言,这个比C#中的using 要害字(dispose模式),以及Java中的 hard-coded的dispose要领都要好很多。这个特性是由C++/CLI中栈工具(局部工具)来提供 的,局部工具自己没错,RAII也是局部工具应有之义。
但问题在于C++/CLI中栈工具的可用性由于很多原因会大打折扣,利用起来已经远远不如 ISO-C++中那样流通。下面列出了损伤其可用性的几大硬伤:
#1、C++/CLI的栈工具并非真的位于栈中
只要范例是ref class,C++/CLI中的栈工具就仍位于托管堆中。仍然利用newobj IL指令 来分派。假如R没有界说析构器(~R)(留意:C++/CLI中的析构器和C#中的析构器完全两回 事),那么下面两行代码实际大将生成完全一样的IL代码:
R r;
R h=gcnew R;
仿佛记得Herb Sutter曾经说过他们未来大概会在真正的要领栈中分派r —— 说实话恐怕只有C++配景的人敢这么“妙想天开”:) 他们此刻只是想在语法层面 让措施员"感受"就像r是从栈中分派的一样。又一个syntax sugar:)
虽然为了对称和语义的完美,有时候还需要在r上应用%——固然背后仍是什么 也没做:)
#2、C++/CLI编译器默认环境下不会自动发生拷贝结构函数和拷贝赋值操纵符
这一点很是令人烦恼,险些让人“望栈工具而却步”。更糟糕的是BCL中的所 有范例都没有提供拷贝结构函数和拷贝赋值操纵符——因为恐怕只有C++/CLI会用 到他们。
话说返来,纵然C++/CLI会自动发生拷贝结构函数和拷贝赋值操纵符,那么担任自BCL的类 型照旧会很贫苦。
#3、假如函数要被其他CLI语言挪用,那么就不能将其参数设计为栈工具
a. static void add(R r){…}
编译出来有一个modopt元数据,所以可以被其他语言挪用,可是假如被其他语言挪用,比 如C#,那么其他语言将是以传值的方法通报引用,而C++/CLI将是通报工具拷贝(要挪用拷贝 结构器),所以语义杂乱,完全不行以这样做。
b. static void add(R% r){…}
由于编译出来都有一个modreq元数据,所以不能被其他CLI语言挪用。
#4、假如函数要被其他CLI语言挪用,那么也不能将其返回值设计为栈工具
a. static R add(){...}
b. static R% add(){...}
两者编译出来都有一个modreq元数据,所以都不能被其他CLI语言挪用。
#5。利用BCL时,假如要通报栈工具,总要利用“莫名其妙”的%操纵符
好比:
String s("abc");
ArrayList list;
list.Add(%s);
实在很欠好,照旧利用追踪引用较量好:
String^ s="abc";
ArrayList^ list=gcnew ArrayList();
list->Add(s);
总结一下:
#1和#5对栈工具的可用性影响不算大,究竟从语义层面来领略,照旧行得通的。
可是,#2、#3、#4的影响就很大。#3和#4使得我们必需放弃利用栈工具来举办互操纵。而 #2会让编写C++/CLI代码很是的不利便——除非你今后不想利用栈工具。
此刻的问题是,是否C++/CLI中的栈工具只是为了得到自动确定性资源接纳而存在?值得 这样做吗?