快速业务通道

泛型编程-转移构造函数(Generic Programming: Move Constructor)

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29
户定义的对象的值的时候,返回一个常量值。例如:

const String operator+(const String& lhs,const String& rhs);

规则4的潜台词是使用户定义的运算符更加接近于内建的运算符可以禁止错误的表达式的功能,就好像想是if (s1+s2==s3)的时候笔误成了if (s1+s2=s3)。如果operator+返回一个常量值,这个特定的BUG将会在编译期间被检测到[译注:返回内建数据类型的值隐含地总是常量的,而用户定义类型则需要显式的用常量限定符指出]。然而,其他的作者[6]推荐不要返回常量值。

冷静的看,任何返回值都是短暂的,它是刚刚被创建就要很快消失的短命鬼。那么,为什么要强迫运算符的使用者获得一个常量值呢?从这个观点看,常量的临时对象看上去就象是自相矛盾的,既是不变的,又是临时的。从实践的观点看,常量对象强迫复制。

现在假定我们同意,如果效率是重要的,最好是避免返回值是常量,那么我们如何使编译器确信将函数的结果转移到目的地,而不是复制他呢?

当复制一个类型为T的对象时,拷贝构造函数被调用。按照下面的设置,我们刚好可以提供这样一个拷贝构造函数实现这个目标。

class String : public mojo :: enabled < string >
{
//...
public:
 String( String& );
 String( mojo :: temporary < String > );
 String( mojo :: constant < String > );
};

这是一个很好的设计,除了一个小细节--它不能工作。

因为拷贝构造函数和其他的函数不完全相同,特别是,对一个类型X来说,在需要X(const X&)的地方定义X(X&),下面的代码将无法工作:

void FunctionTakingX(const X&);
FunctionTakingX(X()); // 错误!不能发现X(const X&)

[译注]

Wang Tianxing在gcc3.2, bcc5.5.1, icl7.0环境下测试结果表明都不会发生错误,并进而查阅了标准,发现Andrei是正确的,如果一定说要有什么错误的话,他没有指出这是实现定义的。

8.5.3 References
5 [...]
— If the initializer expression is an rvalue, with T2 a class type,
and “cv1 T1” is reference-compatible with “cv2 T2,” the reference
is bound in one of the following ways (the choice is implementation-
defined):
— The reference is bound to the object represented by the rvalue
(see 3.10) or to a sub-object within that object.
— A temporary of type “cv1 T2” [sic] is created, and a
constructor is called to copy the entire rvalue object into the
temporary. The reference is bound to the temporary or to a
sub-object within the temporary.93)
The constructor that would be used to make the copy shall be
callable whether or not the copy is actually done.
93) Clearly, if the reference initialization being processed is one
for the first argument of a copy constructor call, an implementation
must eventually choose the first alternative (binding without
copying) to avoid infinite recursion.

我引用了这段标准文本,有兴趣的读者可以自行研究它的含义。

这严重的限制了X,所以我们被迫实现String(const String&)构造函数。现在如果你允许我引用本文的话,在前面我曾经说过:“所以第一个好主意是不要声明一个函数接受常量引用,因为它像一个黑洞一样吞噬所有的对象。”

鱼与熊掌不可兼得,不是吗?

很清楚,拷贝构造函数需要特别的处理。这里的想法是创建一个新的类型fnresult,那就是为String对象提供一个“转移器(mover)”。下面是需要执行的步骤:

前面返回类型为T的值的函数

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号