尽量用pass-by-reference-to-const(const引用)替换pass-by-value(传值)
默认情况下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(传值)的更多相关文章
- 读书笔记_Effective_C++_条款二:尽量以const, enum, inline替换#define
其实这个条款分成两部分介绍会比较好,第一部分是用const和enum替换不带参的宏,第二部分是用inline替换带参的宏. 第一部分:用const和enum替换不带参宏 宏定义#define发生在预编 ...
- void fun() const{}; const void fun(){}; 和void const fun(){}; 的区别?
void fun() const{}; const void fun(){}; 和void const fun(){}; 的区别? const void fun(){};和void const fun ...
- Book. Effective C++ item2-尽量使用const, enum, inline替换#define
##常规变量 c++里面的#define后面的定义部分,是不算代码的一部分的.所以如果你使用#define: #define ASPECT_RATIO 1.653 你希望这个代号ASPECT RATI ...
- int *const && int const * && const int *的区别
ANSIC允许声明常量,常量和变量不同,常量就是不可以改变的量,用关键字const来修饰 比如:const int a int const a 以上两种声明方式是一样的,我们不需要考虑const和in ...
- C++ Prime:const的引用
可以把引用绑定到const对象上,就像绑定到其他对象上一样,我们称之为对常量的引用.与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象: ; const int &r1 = ci; ...
- const 相关知识 const和指针、const和引用
以前老是对const概念不清不楚,今天算是好好做个笔记总结一下.以下内容包括1)常量指针(指针本身是常量),2)指针常量(指针指向的是常量对象),3)常量引用,4)const成员函数. 常量指针,指针 ...
- [转]为什么复制构造函数的参数需要加const和引用
[转]为什么复制构造函数的参数需要加const和引用 一.引言 1.0在解答这个问题之前,我们先跑个小程序,看下调用关系. #include <iostream> using namesp ...
- const的引用
const的引用 对常量的引用:把引用绑定到const对象上,就像绑定到其他对象上一样,不能被用作修改它所绑定的对象: ; const int &r1 = ci;//正确:引用及其对应的对象都 ...
- int *p,cons int *p,int const *p,int * const p,const int * const p,int const * const p的差别
加有constkeyword的几种情况的辨析 const修饰的代码 含义(特点) 等价性 int *p = # 1. 能够读自己 2. 能够通过*p改自己 ...
- 【C++编程基础】(1)—— 函数原型声明、函数模板、引用、const 常引用、const 常量指针
一.函数原型声明: 1.函数声明告诉编译器函数的名称,和如何调用函数(返回类型和参数):函数定义提供了函数的实际主体. 2.强制性的:在C++中,如果函数调用的位置在函数定义之前,则要求在函数调用之前 ...
随机推荐
- 编译GDAL使用最新的HDF库配置文件
HDF库最新版本中的动态库以及目录结构都发生了变化,导致按照之前的博客进行编译GDAL时,会出问题.使用HDF4版本为HDF4-4.2.10,HDF5的版本为HDF5-1.8.12.两个库的目录结构如 ...
- (NO.00005)iOS实现炸弹人游戏(四):游戏数据的初始化(一)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 上一篇我们初步看了一下MainScene类的初始化方法里都做了神 ...
- (NO.00004)iOS实现打砖块游戏(十四):3球道具的实现
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 反弹棒变化道具实现前面已经介绍过了,我们下面可以在小球上做些文章 ...
- OpenCV计算物体的重心坐标(2值图像)
效果图: 代码: // FindGravity.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream& ...
- Android初级教程理论知识(第二章布局&读写文件)
常见布局 相对布局 RelativeLayout 组件默认左对齐.顶部对齐 设置组件在指定组件的右边 android:layout_toRightOf="@id/tv1" 设置在指 ...
- 秒懂ASP.NET中的内置对象
上篇博客,小编主要简单的介绍了一下ASP.NET中的控件,这篇博客,小编主要简单总结一下ASP.NET中的内置对象,七个内置对象分别是:Request.Response.Application.Coo ...
- springMVC对异常处理的支持
无论做什么项目,进行异常处理都是非常有必要的,而且你不能把一些只有程序员才能看懂的错误代码抛给用户去看,所以这时候进行统一的异常处理,展现一个比较友好的错误页面就显得很有必要了.跟其他MVC框架一样, ...
- iOS编程中的音频知识(一):文件格式和数据格式,哦!天哪
要明白实际上每个音频文件都有2各部分组成:它的文件格式(或称之为音频容器),和它的数据格式(或称之为音频编码). 文件格式(audio containers)描述文件自身的格式.实际内部的音频数据可以 ...
- Leetcode_58_Length of Last Word
Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...
- 推荐一个计算机视觉图书:python计算机视觉编程
编辑部的主页:好像没啥用 http://shop.oreilly.com/product/0636920022923.do 每章的代码,github上面的:中文版 https://github.com ...