欢迎光临散文网 会员登陆 & 注册

Effective C++ 第二十条 Prefer pass-by-reference-to-const to pass-by-

2023-01-20 10:40 作者:九思519  | 我要投稿

宁以 pass-by-reference-to-const 替换 pass-by-value

        当前有 Widget 和 SubWidget 两个类,其中 SubWidget public 继承 Widget

有一个函数 call 输出窗口信息,不改变窗口的任何内容

        在 case 1 中,方式一 和 方式二 的结果是一样的,但是执行效率却不同,具体原理可以参考本集合(Effective C++ 读后总结)第十一章最后一段 by value 和 by reference

          由此可知,当传入参数的类型占用内存很大的时候,使用 pass-by-reference-to-const 要高效很多,就以本文的 Widget 为例,pass-by-value 需要创建一个副本,其需要调用一次 Widget 的拷贝构造函数,Widget 中有两个 STL 的 string,那么就是一共调用三次构造函数和三次析构函数,开销大小可想而知。而 pass-by-reference-to-const 就没有这样的开销。自然,在传入参数且不需要对传入内容进行修改的时候,pass-by-reference-to-const 优于 pass-by-value。但是也不是所有时刻都是如此。

        SubWidget 中重载了 Widget 的函数 fun(),两个类的 fun 所执行的功能不一样,下面 case 2

        执行 case 2,发现 call_21 输出为 “Widget”,call_22 输出为“SubWidget”. 造成这个现象的原因是对象切割(slicing)。前文说到, pass-by-value 是拷贝一个传入对象的副本然后对副本进行操作,由于函数 call_21 定义的参数类型是 Widget 而非 SubWidget,所以拷贝副本也是拷贝的 Widget 而非传入 w 的类型 (SubWidget)。所以调用的 fun 是 Widget::fun()。

        pass-by-reference-to-const 是传递该对象地址来实现的(底层原理是这样,引用和指针都是传递地址),不管你 call_22 所设定的参数类型是什么样,只要在调用的时候放进去的事 SubWidget 那么实际使用的就是 SubWidget,而非 Widget。

        凡事也有例外,看起来 pass-by-reference-to-const 处处比 pass-by-value 优秀,但是并不适合于 内置类型、STL迭代器和函数对象 。下面贴一段代码

使用 g++ -std=c++11 -g -o prog 编译,然后使用 objdump -d prog > main.s

        查看 main.s 中的 fun1、fun2、cmp 和 less

fun1 vs fun2 arm64

        在 arm64 中,查看 pass-by-value 和 pass-by-reference-to-const 的汇编代码,除去 ret 语句发现前者为 4 条语句,后者为 5 条语句,说明内置类型 int 通过 pass-by-value 更快。

fun1 vs fun2 X86-64

        在 X86-64 中,除去 ret 语句、 push %rbp 语句和 pop %rbp 语句,pass-by-value 使用 3 条汇编代码,pass-by-reference-to-const 语句使用了 4 条汇编代码,前者效率更高。

        STL 迭代器在这里不做演示,很容易理解,因为 STL 的迭代器底层就是依靠指针来实现的,就是 pass-by-reference,只是不一定是 const 型。

        下面对比 arm64 下 less(函数对象) 和 cmp(函数)

arm64 fun3
arm64 fun4

        对比之后发现,fun3 除去对齐和返回三条语句,使用了 10 条汇编代码,fun4 使用了 11 条汇编代码,所以在 arm64 下对函数对象的传入 pass-by-value 比 pass-by-reference 要高效。

        至于 X86-64 如何留给看文章的读者自己按照上述方式尝试,然后测试结果。当然,你也可以不看会汇编代码,而是用C/C++提供的是时间函数库测试分别调用所花费的时间。

Effective C++ 第二十条 Prefer pass-by-reference-to-const to pass-by-的评论 (共 条)

分享到微博请遵守国家法律