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

本文探讨了C++中转呼叫函数(foward functions)的优化技巧,重点介绍了两个主要改进:使用const引用传递参数以减少不必要的复制,以及考虑函数内联的影响。通过这些改进,可以显著提升函数的执行效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Guru of the Week 条款27:转呼叫函数 (转)[@more@]

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给出的代码规范:

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

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

 

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


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-992727/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10752043/viewspace-992727/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值