您的位置:首页 > 编程语言 > C语言/C++

测试 VS 2010 对 C++ 0x 标准的谨慎支持

2009-08-21 21:28 387 查看
文 / 李博(光宇广贞)




测试版本信息如上。先简述一下背景。话说 C++ 0x 目前仍在“计划”中,新标准将取代 C++ 98/03,并已于目前开始了提案投票,争取今年末获得通过,并于明年公开,因此 C++ 0x 将被定为 C++ 09。

新标准将会更新现有 C++ 的很多方面,其中一项便是“内核语言的扩充”,这也是 C++ 标准委员会关注的主要焦点。该领域的大幅改善包括多线程支持、泛型编程、统一初始化和表现的加强。本文及系列相关文章将先后通过运行期表现、建构期表现、使用性、新机能等最具代表性的四个方面来测试 VS 2010 对 C++ 0x 新标准的支持力度。本篇将先讨论其运行期表现。

VS 2010 之 C++ 0x:运行期表现强化得如何?

该部分的强化旨在提升某些时空性能表现,比如存储器利用以及运行速度等。这里涉及到右值引用与 move 语义、泛化常数表达式等内容。

一、右值引用与 move 语义

查看如下代码。从第一张图可见 IDE 使用红色小波浪标出了数处错误。第二张图便是错误信息。但是该代码却可以 BUILD 成功并且正确运行,第三张图为运行结果信息。可见 VS IDE 对此支持得并不好。代码、错误信息和运行结果的截图如下:













顺便解释一下执行过程。在此使用 IsRightRef 重载函数来区分左值引用与右值引用调用。调用正确表明编译严格遵守左、右值引用以及移动(move)语义。尽管 TestRightRef 函数声明参数表为 int 型的右值引用,然而左值引用与右值引用仅仅是语义上的区分。TestRightRef 函数并不在乎传入的实参是值、或左、右值引用;同样,它也并不能决定 IsRightRef 函数的参数类型。由于“右值”的语义是不具名的,因此对参数 i 的实名调用会使右值引用转义为左值引用,并调用 const int& 重载版本;除非使用 std::move 执行 move 语义,才可调用 int&& 重载版本。有关“移动(move)语义”以及“左值”和“右值”的相关概念,请读者查阅相关资料。

至于右值引用版本的 std::swap 函数,基本模式如下:





由于(且必须)使用 std::move 方法产生“移动语义”,如注释所示,编译器将会绑定右值引用重载方法。必须有 Type 类的右值引用重载方法模板,否则将会绑定到左值引用重载或者默认重载方法上。右值引用重载方法模板声明形式为:

重载构造函数:SbClass ( SbClass && );

重载等号函数:SbClass& operator = ( SbClass&& );

注意重载等号函数接收右值引用,返回左值引用,符合左、右值及等号算符的语义。按我的理解,右值引用重载方法的实质就是“浅拷贝”。“浅拷贝”是唯一且合理的解释,因为“右值”是不会有“副本”的,因此可使用浅拷贝;又由于“右值引用”是“不具名的内存块”,语义上虽然“可移动”,本质上却“动不了”,因此也只能使用浅拷贝。而且,通过检查 VS 编译出来的汇编码可知,它的确就是这么完成的。然而,在“浅拷贝”过程中临时对像的产生依旧未能避免。

这里多说一句,右值引用重载中,无法使用移动语义,比如 *this = std::move ( sb ),因为这样做会使编译器继续调用右值引用等号重载,从而无限递归,直至堆栈溢出崩溃;或者直接给地址 this = &sb,首先 this 只读,其次,由于“右值”本身就有“临时对像”的含义,所以语义上是不允许取址操作的。综上,右值引用重载方法中的赋值过程只能使用默认赋值构造函数,该函数执行左值语义,其实就是浅拷贝。关于微软 VC 开发团队官方博客对于右值引用的示例,请见《Rvalue References: C++ 0x Features in VC 10》

通过以上两个例子可以看出,“右值引用”的语义在实现上与标准中理想的差距。首先,由第一个例子可知,一旦使用中将“右值引用”“具名”,语义上立即转为“左值引用”。再者,由第二个例子可知,“右值引用”并未真正实现“移动语义”,而是使用“浅拷贝”,而且依然避免不了“临时对像”的产生。

最后指出,std::move 并未能在“智能感知”中显示,如图:





关于 VC 10 IDE 在针对 C++ 0x 的智能感知方面的官方文章,请参考《Intellisense and Browsing with C++ 0x》

二、泛化的常数表达式

也就是 constexpr 关键字,VS 2010 目前拒绝加入该关键字,而该关键字的在标准中的命运也并不乐观……该 constexpr 关键字是由 Bjarne Stroustrup 等人提案加入的,缘何导致现在对它的通过变得举步唯艰呢?

constexpr 出了问题连锁反应影响到一系列提案,包括 BS 等人提交的 Initializer List(N1493N1509N1890N1919N2100 方案中提到的新特性同样为 VS 2010 拒绝,因为该方案中的特性需要 constexpr 的支持。

关于这些问题更详尽的分析,请参考《C++ 0x 即将夭折的新关键字 constexpr 为 VS 2010 拒绝》

参考:

《VS 2010 并不支持 C++ 0x 标准中的 extern template》

《维基百科:C++ 0x》

《C++ 0x 即将夭折的新关键字 constexpr 为 VS 2010 拒绝》

《C++ 0x(C++ 09)新标准全部革新提案文档列表》

《C++ 中 export 关键字的尴尬处境》

《从 C++ 模板元编程生产质数看 F# 函数式编程思想》

《由 C++ 模板元编程看 F# 对链表的处理,兼谈 C 系语言和 FP 的优劣》

《我眼中的微软大战略和中国软件之殇》

《微软全部产品整理》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: