快速业务通道

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

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29
::operator=(const String& rhs);
template< class T > vector< T >::push_back(const T&);

第三条规则试图避免意外的大对象的复制。然而,有时第三条规则强制不必要的复制进行而不是阻止它的发生。考虑下面的Connect函数:

void Canonicalize(String& url);
void ResolveRedirections(String& url);
void Connect(const String& url)
{
  String finalUrl=url;
  Canonicalize(finalUrl);
  ResolveRedirections(finalUrl);
  //...使用finalUrl...
}

Connect函数获得一个常量引用的参数,并快速的创建一个副本。然后进一步处理副本。

这个函数展示了一个影响效率的常量引用的参数使用。Connect的函数声明暗示了:“我不需要一个副本,一个常量引用就足够了”,而函数体实际上却创建了一个副本。所以假如现在这样写:

String MakeUrl();
//...
Connect(MakeUrl());

可以预料MakeUrl()会返回一个临时对象,他将被复制然后销毁,也就是令人畏惧的不需要的复制模式。对一个优化复制的编译器来说,不得不作非常困难的工作,其一是访问Connect函数的定义(这对于分离编译模块来说很困难),其二是解析Connect函数的定义并进一步理解它,其三是改变Connect函数的行为以使临时对象和finalUrl融合。

假如现在将Connect函数改写如下:

void Connect(String url)  //注意按值传递
{
  Canonicalize(url);
  ResolveRedirections(url);
  //... 使用 url ...
}

从Connect的调用者的观点来看,绝对没有什么区别:虽然改变了语法接口,但是语义接口仍然是相同的。对编译器来说,语法的改变使所有事物都发生了改变。现在编译器有更多的余地关心url临时对象了。例如,在上面提到的例子中:

Connect(MakeUrl());

编译器不一定要真的聪明到将MakeUrl返回的临时对象和Connect函数需要的常量融合。如果那么做,确实会更加困难。最终,MakeUrl的真正结果会被改变而且在Connect函数中使用。使用常量引用参数的版本会使编译器窒息,阻止它实行任何优化,而使用传值参数的版本和编译器顺畅的合作。

这个新版本的不利之处在于,现在调用Connect也许生成了更多的机器码。考虑:

String someUrl=...;
Connect(someUrl);

在这种情况下,第一个版本简单的传递someUrl的引用[译注:从非常量到常量是标准转型]。第二个版本会创建一个someUrl的副本,调用Connect,然后销毁那个副本。随着调用Connect的静态数量的增长,代码大小的开销同时增长。另一方面,例如Connect(MakeUrl())这样的调用会引入临时对象,在第二个版本中又刚好生成更少的代码。在多数情况下,大小差异好像不会导致问题产生[译注:在某些小内存应用中则是一个问题,例如嵌入式应用环境]。

所以我们给出了一套不同的推荐规则:

[规则1]如果函数内部总是制作参数的副本,按值传递。

[规则2]如果函数从来不复制参数,按常量引用传递。

[规则3]如果函数有时复制参数,而且关心效率,则按照Mojo协议。

现在只留下开发Mojo协议了,不管它是什么。

主要的想法是重载同样的函数(例如Connect),目的是辨别临时的和非临时的值。后者也称为左值(lvalue),因为历史原因,左值因为可以出现在赋值运算符的左边而得名。

现在开始重载Connect,第一个想法是定义Connect(const String&)来捕捉常量对象。然而这是错误的,因为这个声明“吞吃”了所有的String对象,不管是左值(lvalue)或者临时对象[译注:前面提到过,非常量可以隐式转型为常量,这是标准转型动作]。所以第一个好主意是不要声明接受常量引用的参数,因为它像一个黑洞一样,吞噬所有的对象。

第二个尝试是定义Connect(String&)试图捕获非常量的左值。这工作良好,特

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站: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号