Note of Justin

关于工作和读书的笔记

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  47 Posts :: 0 Stories :: 45 Comments :: 0 Trackbacks

留言簿(14)

搜索

  •  

积分与排名

  • 积分 - 51778
  • 排名 - 433

最新评论

阅读排行榜

评论排行榜

[原创文章欢迎转载,但请保留作者信息]
Justin 于 2009-12-17

C++传递对象的时候默认是传值的(pass-by-value),而这样的传递自然是昂贵的:这当中包含了临时对象的构造/析构,以及临时对象中的对象的构造/析构,运气背点还可能有对象中的对象中的对象的构造/析构……(有好的不学,去学C@#¥%)

相对于传“值”,一个更好的替代方法是传“const引用”(pass-by-reference-to-const)。
传值与传指针的一个区别是,通过传值传递的对象并不是原来的对象,而是一个复制品,所以随便你打它骂它,真身都不会受到影响。
而通过传指针的对象和原来的对象就是同一家伙,改动一个另外一个也受到相同的影响。而这有时候并不是我们想要的结果。
考虑到传值代价太高,传“const引用”就成了一个很好的替代品。

传“const引用”的另外一个好处在于避免了“剥皮问题”(slicing problem,侯捷大师的版本是“对象切割问题”,我用这个中文名字是为了更容易记住:))
书上的代码已经说得很清楚,这里就大概带过:用传值方式传参的函数,如果某参数的类型是一个父类对象,而实际传递的参数是一个子类对象,只有该对象的父类部分会被构造并传递到函数中,子类部分的成员,作为父类对象的“皮”,就被血淋淋的剥掉了……
而如果用传“const引用”方式,就没有这种惨无人道的状况:本来父类的指针就可以用来指向一个子类对象,天经地义。

但凡有规矩就有例外,对于内置类型(bulit-in type)对象以及STL中的迭代器、函数对象,Scott还是建议使用传值方式传递,原因是他们本来就是被设计成适合传值传递的。(个人观点:大师说:“……it's not unreasonable to choose pass-by-value。”,注意这里有句潜台词:其实对以上类型用传“const引用”方式传递也是可以的。)
如果你认为上面两种情况可以用传值传递是因为它们,比如说内置类型对象,的大小本来就小,进而得出小数据类型就可以用传值传递,就打错特错了。原因见第一段:小对象的构造/析构过程完全可能很恐怖。
再退一步,哪怕某个类型很小,它的构造/析构函数也简单到可以忽略不计,我们还是不能以此断定可以用传值传递这种类型的对象:因为编译器往往会做出一些蠢事。书中的一个例子是,对于一些编译器可以接受把一个double类型对象存入寄存器,但是如果你给它一个只有一个double成员的对象交给它,它却拒绝将该对象存入寄存器。(什么事让编译器插一手,不是问题也有了问题……)
最后还有个理由,虽然某对象现在很小,可是随着社会的发展人类的进步,有可能两年后它就会变成一个庞然大物,到时候用传值也会变得不合适。

因此,还是老实点:除了内置类型和STL的迭代器、函数对象外,其他的对象传递时,用传“const引用”代替传值吧。

posted on 2010-01-04 08:14 Justin.H 阅读(2276) 评论(2)  编辑 收藏 引用 所属分类: Effective C++ 炒冷饭

Feedback

# re: Effective C++ 炒冷饭 - Item20 用传“const引用”取代传“值” 2010-01-05 15:55 as3
这个系列不错,每个话题里面带点简短的示例code更好  回复  更多评论
  

# re: Effective C++ 炒冷饭 - Item20 用传“const引用”取代传“值” 2010-01-06 08:25 Justin.H
谢谢as3的提醒,以后我尽可能加些代码进去炒:)  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理