Effective C++ rule 20.传参与传引用
2017-09-05 09:18
127 查看
前言
Rule 20 阐述了我们在设置函数的形参时,尽量以pass by reference const 的形式,少用pass by value.主要基于效率和行为考虑的。代码讲解
#include <stdio.h> #include <iostream> #include <string> using namespace std; class Person { public: string name; public: Person() { } virtual ~Person() { } public: virtual void say() const { cout << "Person:I am " << name; } }; class Student :public Person { public: Student() :Person() { } ~Student() { } public: virtual void say() const { cout << "Student: I am " << name; } }; void Sayv(Person p) { p.say(); } void Sayr(const Person& p) { p.say(); } int main() { Student stu; Sayv(stu); Sayr(stu); return 0; }
1.我们来看调用Sayv与Sayr的开销: Sayv(Person p) 传入的时候需要调用Person的复制构造函数,在Sayv()结束的时候,需要调用Person的析构函数。Sayr(Person &p)没上面的步骤。
2.再看两个函数输出什么:
Sayv()调用的是Person的say()函数。而Sayr()调用的Student类的say()函数。Sayr(Person &p)其实就是使用了多态性来调用say()函数。
Sayv()因为是pass by value.导致stu被切割成只剩下基类Person的东西了。
为什么内置类型一般使用pass by value会更高效安全
文中还提到我们编程验证一下:
int fv(int i) { return i*i; } int fr(const int &i) { return i*i; } int main() { int x = 5; int y = fv(x); int z = fr(x); return 0; }
汇编代码:
60: int x = 5; 010364FF mov dword ptr [x],5 把5存入x对应的内存中 61: int y = fv(x); 01036506 mov eax,dword ptr [x] 取x内存中存储的值到eax 01036509 push eax 传入eax 0103650A call fv (010312B2h) 0103650F add esp,4 01036512 mov dword ptr [y],eax 62: int z = fr(x); 01036515 lea eax,[x] 取x变量的有效地址到eax,就是传入x的地址进去。 01036518 push eax 传入eax. 01036519 call fr (010314BFh) 0103651E add esp,4 01036521 mov dword ptr [z],eax
其实对于内置类型(包括指针),传参数还是传引用效率上是差不多的,因为两个都要访问内存若干次。但是传参数的版本可以在不加const的情况下保证函数内部的操作不会影响到原来的变量X。
另外!
严格来说,传参效率还要低一些,因为它需要先取x的地址,然后将x的地址传到MAR寄存器,再从地址总线定位到内存单位,通过数据总线拿回X的值;而传引用的话只需要取x的地址,没有接下来访存的操作。
总结:
一般情况下,pass by reference const会比pass by value 少了很多复制构造函数和析构函数的调用,从这个角度来看pass by reference const 是很受推崇的pass by reference const利用多态性,可以避免pass by value对子类进行切割的问题。我们一般不想看到子类被切割了,但是也不排除某些场合下 我们就需要这个效果。
pass by reference const的函数其实还有一个不太好的问题就是:因为传入的是一个常引用,导致在函数内部只能调用对象的const方法!比如上面的例子中 say()就需要是const函数。当然这或许也不是什么问题,在这个规定下,开发人员开发出来的类将更加规范,严格遵循const 对象只能调用const方法来保证对象的一致性。不过,个人还是更喜欢没有带const的pass by reference ,哈哈哈
相关文章推荐
- More Effective C++----效率 & (16)牢记80-20准则(80-20 rule)
- More.Effective.C++牢记 80-20 准则(80-20 rule)
- More Effective C++:指针与引用的区别
- 函数条款明明白白c++ effective c++ 条目16-20
- More Effective C++议题【一】:指针和引用
- Effective C++,rule 1,View C++ as a federation of languages
- Effective Modern C++ 条款25 对右值引用使用std::move,对通用引用使用std::forward
- More Effective C++:指针与引用的区别
- More Effective C++----(20)协助完成返回值优化
- C++中传值方式传参与引用常量传参的使用规则
- Effective C++ 学习笔记(20)
- more effective c++——Item M29 引用计数(三)带引用计数的基类的实现
- Effective C++——》条款20:宁以pass by refrence to const 替换 pass by value
- 指针和引用的区别(More Effective c++ )
- More Effective C++:通过引用捕获异常(转)
- 读书笔记 effective c++ Item 10 让赋值运算符返回指向*this的引用
- More Effective C++ 阅读笔记(九)--要用引用(reference)捕获异常
- Effective Modern C++ 阅读笔记(最新颖的名词是‘通用引用’和‘完美转发’,C++语言真是博大精深,哈哈)
- More Effective C++:指针与引用的区别
- 引用与指针的区别,摘自More Effective C++