Guru of the Week 条款27:转呼叫函数

原创 2002年08月05日 10:20:00

GotW#27 转呼叫函数(Forwarding Functions)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

难度:3 / 10

怎样将转呼叫函数写得最好?原本答案很简单,但我们已经知道C++语言近来发生了微妙的变化。

问题

转呼叫函数对于将任务传递给其它函数或对象时很有用,尤其当它们被设计得很高效时。

评论一下下面这个转呼叫函数。你试图修改它吗?如果是的话,怎么来?

    // file f.cpp

    #include "f.h"

    /*...*/

    bool f( X x ) {

        return g( x );

    }

(说明:本次GotW的目的之一是阐明在July [1997]于London加入到C++语言中的一个微妙改进所造成的后果。)

解答

转呼叫函数对于将任务传递给其它函数或对象时很有用,尤其当它们被设计得很高效时。

关键点是:效率。

评论一下下面这个转呼叫函数。你试图修改它吗?如果是的话,怎么来?

    // file f.cpp

    #include "f.h"

    /*...*/

    bool f( X x ) {

        return g( x );

    }

有两个主要改进可使得这个函数更高效。第一个应该总被采用,第二个需要权衡。

1.传参时使用传const的引用代替传值

“这不会造成混乱吗?”你可能会问。不,它不会,至少在这种情况下。直到最近,C++语言才规定:因为编译器可以确保参数x除了被传递给g()外没有被其它地方使用,编译器可以将x完全优化掉。例如,这样的代码:

    X my_x;

    f( my_x );

编译器可以:

a)产生一个my_x的拷贝供f()使用(就是f()的代码体中的形参x),然后将这个拷贝传给g();或者

b)直接将my_x传给g()而不生成拷贝,因为它注意到这个额外的拷贝除了作g()的参数外根本没被使用。

后者更高效,不是吗?这是编译器试图作的优化,不是吗?

是的,是的,但只到July 1997的London会议。在那次会议上,“限制编译器作这种取消额外拷贝的优化”的提案得到了更多的支持。〖注1〗编译器唯一可以取消额外拷贝构造的地方是“返回值优化”(在你的C++宝典中查询细节吧)和“临时对象”。

这意味着,象f这样的转呼叫函数,编译器被要求产生两份拷贝。既然我们(作为f的作者)知道这个额外的拷贝不是必须的,我们应该按照通常的办法将x申明为const X&型的参数。

(注意:如果我们一直就是这么做的,而不是依赖于知道编译器被允许做些什么,那么,这个规则的变化不会对我们造成任何影响。这就是一个“简单就是美”例子--尽可能避开语言的细枝末节,别耍小聪明。)

2.函数内联

这个需要权衡。要之,默认将所有函数都实现为外联,有选择地将确实需要内联以提高效率的函数实现为内联。

当你将函数内联时,积极面是你避免了对f函数的调用的额外开销。

消极面是内联f暴露了f的实现,并使得用户的代码依赖于此实现,当f被改变时,所有的用户代码都必须被重编译。更严重的是,用户代码现在至少需要知道函数g()的原型,这有点恶心,因为用户根本没有直接调用函数g,原本可以根本不需要知道它的原型的(至少,从我们的例子上,是这样的)。于是,如果g()自己发生了变化,接受其它类型的其它参数时,用户的代码将变得也需要知道这些类型的申明。

内联和非内联都可以。必须在优缺点间进行权衡,取决于f现在是怎样被使用的以及使用的广泛程度,和将来可能变为怎样被使用的以及使用的广泛程度。

GotW给出的代码规范:

l         传参时,用传const的引用来代替传值

l         避免函数内联,除非profiler告诉你有这个必要(程序员在猜测效能瓶颈点方面是很不准的)

 

1:这个改进是必要的,它避免了编译器未经允许地省略拷贝构造时带来问题,尤其当拷贝构造有副作用时。很多时候,代码需要计算对象的拷贝数目。

Guru of the Week 条款17:转型

GotW #17 Casts著者:Herb Sutter翻译:K ][ N G of @rk™[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week栏目,其著作权归原著者...
  • kingofark
  • kingofark
  • 2001年12月18日 09:26
  • 1076

Guru of the Week 条款05:覆写虚拟函数

 GotW #05 Overriding Virtual Functions著者:Herb Sutter      翻译:kingofark[声明]:本文内容取自www.gotw.ca网站上的Guru...
  • kingofark
  • kingofark
  • 2001年10月23日 20:12
  • 1208

Guru of the Week 条款14:类之间的关系(上篇)

GotW #14 Class Relationships Part I著者:Herb Sutter     翻译:kingofark[声明]:本文内容取自www.gotw.ca网站上的Guru of ...
  • kingofark
  • kingofark
  • 2001年10月29日 20:05
  • 1111

Guru of the Week 条款17:转型

GotW #17 Casts著者:Herb Sutter翻译:K ][ N G of @rk™[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week栏目,其著作权归原...
  • hejishan
  • hejishan
  • 2008年04月08日 23:41
  • 185

Guru of the Week 条款19:自动转换

GotW #19 Automatic Conversions著者:Herb Sutter翻译:K ][ N G of @rk™[声明]:本文内容取自www.gotw.ca网站上的Guru of the...
  • kingofark
  • kingofark
  • 2001年12月24日 13:38
  • 1127

Guru of the Week 条款25:auto_ptr

GotW#25 auto_ptr难度:8/10问题考虑下面的代码:那些是好的,那些是安全的,那些是合法的, 那些是非法的?auto_ptr source() { return new T(1); } ...
  • taodm
  • taodm
  • 2002年08月05日 10:20
  • 1153

Guru of the Week 条款02: 临时对象

GotW #02 Temporary Objects著者:Herb Sutter      翻译:kingofark[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week...
  • kingofark
  • kingofark
  • 2001年10月23日 20:08
  • 1005

Guru of the Week 条款00:kingofark和Guru of the Week

 Revision 1.0Guru of the Week 条款00:kingofark和Guru of the Week作者:kingofark难度:0 / 10(本条款是GotW的译者kingof...
  • kingofark
  • kingofark
  • 2001年10月24日 13:48
  • 1039

Guru of the Week 条款13:面向对象程序设计

GotW #13 OOP著者:Herb Sutter      翻译:kingofark[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week栏目,其著作权归原著者本人所...
  • kingofark
  • kingofark
  • 2001年10月24日 08:49
  • 1141

Guru of the Week 条款18:Iterators(迭代子)

GotW #18 Iterators著者:Herb Sutter翻译:K ][ N G of @rk™[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week栏目,其著...
  • hejishan
  • hejishan
  • 2008年04月08日 23:40
  • 165
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Guru of the Week 条款27:转呼叫函数
举报原因:
原因补充:

(最多只允许输入30个字)