基础备忘:关于传值与传引用的讨论

举报
ShaderJoy 发表于 2021/12/29 23:11:24 2021/12/29
【摘要】 阅读目录 效率问题对象的切割问题STL中的使用情况   正文 回到顶部 效率问题 对于用户自定义的类型来说,传引用一般要比传值高效。传引用不需要经过对象过程,在《Effective C++》中作者举了个例子: class Base{ pubilc: Base(); ...

 

正文

效率问题

对于用户自定义的类型来说,传引用一般要比传值高效。传引用不需要经过对象过程,在《Effective C++》中作者举了个例子:


   
  1. class Base
  2. {
  3. pubilc:
  4. Base();
  5. ~Base();
  6. private:
  7. std::string b1;
  8. std::string b2;
  9. }
  10. class Derive : public Base
  11. {
  12. public:
  13. Derive();
  14. ~Derive();
  15. private:
  16. std :: string d1;
  17. std ::string d2;
  18. }

此刻我们拥有一个派生类对象derive 。对derive传值的结果是共需要进行六次的构造函数的调用:对象本身的构造函数,对象内部数据成员string的构造,对象基类部分的构造函数,对象基类数据成员string的构造。同样的,待对象生命结束后,还要经历6次析构函数的调用。而传引用则不用进过如此多的构造与析构,甚至一次都不用。
对内置类型来说,传值的效率往往要高于传引用。内置类型包括了int,float ,double,指针类型等等。看下面的程序:


   
  1. void f(int i)
  2. {
  3. i = i + 1;
  4. }
  5. void g(int & i)
  6. {
  7. i = i + 1;
  8. }
  9. int main()
  10. {
  11. int i=10;
  12. f(i);
  13. g(i);
  14. }

当通过传值调用函数f()时,其汇编代码为:

当通过传引用调用函数g()时,其汇编代码为:

可以看到,传引用比传值多了一次寻址操作,这是因为引用的实现往往基于指针,因此传引用通常意味着真正传递的是指针。

总结:

  1. 对内置类型来说,通常传值更高效。
  2. 对用于自定义类型来所,传值要经历构造与析构过程,一般比较耗时。

对象的切割问题

传值有时会引起对象的切割问题。就上面所示的两个类,当我们定义如下函数并进行传值调用时:


   
  1. void func(Base B)
  2. {
  3. ...
  4. }
  5. int main()
  6. {
  7. Derive A;
  8. func(A);
  9. }

编译器将调用Base类的复制构造函数来初始化B,初始化数据来源于A,但构造结果是个Base类对象:也就意味着A的特有部分的数据被切割掉了。在函数func中,B的行为是一个Base的行为而不是Derive的行为。
通过传引用,能够避免切割的问题


   
  1. void func(Base & B)
  2. {
  3. ...
  4. }
  5. int main()
  6. {
  7. Derive A;
  8. func(A);
  9. }

此时在函数func内,对象B实际类型为Derive,通俗地将,B就是A。若希望在func中使用到实参的特性,传引用能够保证这一点【但经过我测试:当Base类和Derive类含有相同方法(非虚函数)时,调用的还是Base类,除非该Base类的方法为虚函数,调用的才是Derive所对应的方法】。

STL中的使用情况

如果你打开STL中的源码,你会发现容器的iterator都是通过传值形式传参。在《Effective C++》中指出,对于内置类型、STL 迭代器和 STL 仿函数,pass-by-value 也是可以的,一般没有性能损失。在 x86-64 上,对于只有一个 指针成员且没有自定义拷贝构造函数的类,传值是可以通过寄存器进行的,就像传递普通 int 和指针那样。如上所示,传值是可以比传引用快的,因为它少了一次解引用的操作。

(完)

文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/52460184

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。