默认情况下C++以pass-by-value传递对象至函数(或从函数返回)。

eg1:

class Person {
public:Person();virtual ~Person();
private:std::string name;std::string address;
};class Student: public Person {
public:Student()~Student();
private:std::string schoolName;std::string schoolAddress;
};

考虑下面调用函数:

bool validateStudent(Student s); // 函数以 by value 方式接受参数
Student plato;
bool platoIsOk = validateStudent(plato); // 调用函数

Student的copy构造函数会被调用,以plato为蓝本将s初始化。而当validtaeStudent返回时s会被销毁。详细深究的话,应该是以by value方式传递一个Student对象会导致调用一次Student copy构造函数,一次Person copy构造函数,4次String copy构造函数;相应销毁时总共需要调用6次析构函数。所以总成本是“六次构造函数和六次析构函数”!

使用pass by reference to const进行回避:

bool validateStudent(const Student& s);

这种传递方式效率就高很多,没有任何构造函数或析构函数被调用,因为没有对象被创建。这里的const使用是重要的,不这样做的话调用者会忧虑validateStudent会不会改变他们传入的哪个Student。

以by reference方式传递参数还可以避免slicing(对象切割)问题。

如果函数参数是基类对象,当传入一个派生类对象时,会造成派生类对象相比基类对象“之所以是个派生类对象”的所有特性化信息都会被切除。解决切割(slicing)问题的办法,就是以by reference to const的方式传递参数。

闲谈:有一次面试的时候问到了我这个问题,没有很好的回答上来“多态发生为什么需要传指针而不直接传递对象,传递对象有什么后果?”,现在可以很好的总结出答案。

由C++编译器的角度来看,references往往以指针实现出来,一次pass by reference 通常意味真正传递的是指针。如果对象属于内置类型(例如int),pass by value往往比pass by reference的效率高些(原因请看:C++ 传参时传内置类型时用传值(pass by value)方式效率较高)。

1、内置类型都相当小,因此有人觉得,小型types都是pass-by-value的合格候选人,这个理论不可靠,对象小并不意味着其copy构造函数并不昂贵。许多对象(包括大多数STL容器)内容的东西只比一个指针多一些,但复制这种对象却需承担“复制那些指针所指的每一样东西”,那将非常昂贵。

2、即使小型对象拥有并不昂贵的copy构造函数,但效率优化上可能有争议。某些编译器会针对“内置类型”进行优化,比如某些编译器拒绝把只由一个double组成的对象放进缓存器,但是很乐意在一个正规基础上对光秃秃的doubles那么做。这种情况下,更应该以by reference方式传递此等对象。

3、作为一个用户自定义类型,其大小容易有所变化。一个type目前虽然小,将来也许会变大,因为其内部实现可能改变。

结论:
        1、尽量以pass-by-reference-to-const替换pass-by-value,前者通常毕竟高校,并可避免切割问题(slicing problem)。

2、以上规则并不适用于内置规则,以及STL的迭代器和函数对象。对它们而言,pass-by-value往往比较适当。

尽量用pass-by-reference-to-const(const引用)替换pass-by-value(传值)相关推荐

  1. Effective C++条款20解读:宁以pass by reference to const替换pass by value

    我们先来看一个简单的程序: #include <iostream> using namespace std;class A { private:string name;string add ...

  2. Effective C++ 条款02:尽量使用const,enum,inline替换#define

    Effective C++ 条款02:尽量使用const,enum,inline替换#define 用另一句话说:用编译器代替预处理器比较好. 举个例子:加入定义一个常量: #define ASPEC ...

  3. pass by value 与pass by reference 小结

    缺省条件下,c++都是以pass by value形式传递函数参数的,而值传递的参数,编译器知道这个参数收到保护,不会修改其值,实际上修改的都是通过拷贝构造函数另外创建的参数副本,当函数返回时还要调用 ...

  4. [C++学习] effective c++ 笔记 pass by value ,pass by reference

    在编写函数的返回值和形参的时候,能 传引用(pass by reference) 就不要 传值 (pass by value). 这样是为了少调用 copy constructor ,可以提高效率. ...

  5. C++ 笔记(15)— 引用(声明引用、引用作为参数、引用作为函数返回值、const 用于引用)

    引用是变量的别名.也就是说,它是某个已存在变量的另一个名字.一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量. 1. 创建引用 要声明引用,可使用引用运算符 & ,如下面的 ...

  6. 关键字const——const char*和char* const

    文章目录 概述 const char* 和char* const define 和 const 概述 关键字const一般用来修饰定义常量.使用const修饰的变量就不能被更改了.这是因为在编译时,编 ...

  7. 方法参数中pass by reference(传引用)和 pass by value(传值)的区别

    如果你把㆒个名为foo的对象作为参数传给某个函数,那么「对参数赋值」意味改变foo,使它引用(参考.指涉.指向)另㆒个对象.如果你在「被传入对象」身㆖进行什么操作,那没问题,我也总是这样干.我只针对「 ...

  8. void fun() const{}; const void fun(){}; 和void const fun(){}; 的区别?

    const void fun(){};和void const fun(){};两个相同. 如果采用"按址传递方式"的函数返回值加const 修饰,那么函数返回值(即地址)的内容不能 ...

  9. int *p,cons int *p,int const *p,int * const p,const int * const p,int const * const p的区别

     加有const关键字的几种情况的辨析 const修饰的代码 含义(特点) 等价性 int *p = # 1.       可以读自己 2.       可以通过*p改自己 3.       可以 ...

  10. 容器的访问元素的成员函数(front,back,下标和at)返回的都是引用,如果顺序容器是const的对象,那么返回的是const的引用

    顺序容器的访问元素的成员函数(front,back,下标和at)返回的都是引用,如果顺序容器是const的对象,那么返回的是const的引用,下面有个例子说明问题: #include <iost ...

最新文章

  1. jittor和pytorch生成网络对比之gan
  2. mysql导出长数字到excel避免显示为科学记数法 解决方法
  3. php7安装kafka扩展(已经测试)
  4. 【Linux】一步一步学Linux——mv命令(30)
  5. 坐标转换 计算机图形学_计算机图形学的转换类型
  6. php cve-2014-9427漏洞,WEB应用漏洞-温州特种设备检测研究院.DOC
  7. Java LinkedList公共对象pollLast()方法(带示例)
  8. yum清缓存_linux yum清除var目录下缓存的方法
  9. 单体预聚合的目的是什么_第七章 配位聚合
  10. Pandas 文本数据方法 strip( ) lstrip( ) rstrip( )
  11. 20 分钟教你搞懂 Git!
  12. ROS学习(六)—— 理解ROS节点
  13. Java工程师如何在Docker上进行开发
  14. Android app修改IMEI号
  15. 关于origin2019的安装教程
  16. 华为平板解锁工具_华为平板M6 10.8英寸首发评测 办公+影音+智能全面开花
  17. IT人的算法书单:挖掘程序的灵魂
  18. 南航率先启用“手机登机”
  19. 第三集 be 动词一般动词的过去式
  20. ROS2/DDS/QoS/主题的记录

热门文章

  1. 京东数科:无偿驰援 多款智能产品服务防控第一线
  2. keep-alive上加v-if导致缓存失效
  3. 数字后端面试100问(校招版)
  4. 《5G时代:生活方式和商业模式的大变革》读书笔记和总结
  5. A. Arena of Greed【贪心+特判】
  6. 关于 Redis 的 懒惰删除 (十三)
  7. android studio记账,Android Studio--家庭记账本(三)
  8. 腾讯AI Lab发布智能创作助手「文涌 (Effidit)」,用技术助力「文思泉涌」
  9. AWS 服务器登录和配置
  10. android线刷软件,android线刷一般用什么软件?哪一个好用一些?