[Effective C++ --020]宁以pass-by-reference-to-const替换pass-by-value
前言:
我们都用过C的值传递方式,那么在C++情况下,值传递是怎样工作的呢?
比如:
int foo(int x);
int i;
foo(i);
1.程序内部先取得i的一个副本
2.将副本传递到foo函数
3.foo返回
这些副本的都是由拷贝构造函数产出的,当参数过多或者逻辑复杂时,就可能使得值传递成为费事的操作。
第一节:用pass-by-reference-to-const替换pass-by-value
我们先看类的值传递过程:
class A {
public:
A() {cout << "Call A\n"; }
A(const A& aCopy) { // 拷贝构造函数
a = aCopy.a;
}
virtual ~A(){}
private:
string a;
};
class B: public A {
public:
B() {cout << "call B\n"; }
~B() {}
private:
string b;
};
void foo(B b) {
return;
}
接下来我们这么调用:
B b1; // 会直接先调用A的构造函数
// 再调用B的构造函数
foo(b1); // 副本调用A的构造函数
// 再调用B的构造函数
上面并不是调用的所有数据,因为我们还有类的string成员!
在每次构造的时候都会调用string的构造函数,因此除了调用一次A的构造函数和一次B的构造函数,我们还额外调用了两次string的构造函数。
另外,我们还需要调用相对应的析构函数,因此上面的代码调用次数总和为:4次构造函数+4次析构函数。
简单的一个赋值,就导致这么多次函数调用,效率是问题!
方案:我们可以使用const引用来解决这个问题。在这种方式下,任何构造函数和析构函数都不需要调用。
void foo(const B& b) {
return;
}
因为引用是直接对对象进行操作的,不存在副本之说。另外定义为const,是为了不让传递的实参被误改!
除了调用函数次数减少,使用const引用还可以带来以下的好处。
★避免对象切割问题(slicing)
用一个形象的例子来解释:
class A {
public:
A() {cout << "Call A\n"; }
A(const A& aCopy) {
a = aCopy.a;
}
virtual ~A(){}
private:
string a;
};
class B: public A {
public:
B() {cout << "call B\n"; }
~B() {}
private:
string b;
};
void foo1(A a) {
return;
}
如果我们这个时候将子类对象传入foo1()函数。
B b1;
foo1(b1); // 子转父
在这个时候,b1在值传递的时候会被认为是一个基类对象,从而产生一个基类副本,A的拷贝构造函数被会调用,于是子类B中的特性会被全部切割,仅仅留下一个基类对象!
而解决切割问题的最好方法:就是使用const引用传值!
void foo1(const A& a) { // 不再调用A的拷贝构造函数!
return;
}
第二节:基本类型的传递
如果我们去探寻C++编译器的底层,就会发现:引用往往以指针实现出来,因此通过指针传递通常意味着真正传递的是指针。
因此,对于内置类型而言,值传递的效率其实比引用传递的效率高些。
对于STL的迭代器和函数对象而言,这个结果也是适用的。
◆总结
1.尽量以pass-by-reference-to-const替换pass-by-value。前者通常比较高效,并可避免切割问题(slicing problem);
2.在针对内置类型以及STL迭代器和函数对象时,一般还是值传递比较高效。
[Effective C++ --020]宁以pass-by-reference-to-const替换pass-by-value的更多相关文章
- [GeekBand ] 利用 pass by reference -to -const 编写高效规范的 c++代码
本文参考资料 : GeekBand 侯捷老师,学习笔记 Effective C ++ 侯捷译 条款20 开发环境采用:VS2013版本 首先:分析值传递的缺点 (一) class Person{ p ...
- 值传递:pass by value(按值传递) 和 pass by reference(引用传递)-[all]-[编程原理]
所有的编程语言,都会讨论值传递问题. 通过一个js示例直观认识 //理解按值传递(pass by value)和按引用传递(pass by reference) //pass by value var ...
- 《Effective C++》读书笔记 条款02 尽量以const,enum,inline替换#define
Effective C++在此条款中总结出两个结论 1.对于单纯常量,最好以const对象或enum替换#define 2.对于形似函数的宏,最好改用inline函数替换#define 接下来我们进行 ...
- Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结
这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...
- Effective C++_笔记_条款03_尽可能使用const
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 关键字const多才多艺,语法变化多端.关于const的基本用法 ...
- 对常量的引用(reference to const)的一般用途(转载)
如果是对一个常量进行引用,则编译器首先建立一个临时变量,然后将该常量的值置入临时变量中,对该引用的操作就是对该临时变量的操作.对C++常量引用可以用其它任何引用来初始化:但不能改变. 关于引用的初始化 ...
- Effective C++ -----条款23:宁以non-member、non-friend替换member函数
宁可拿non-member non-friend函数替换member函数.这样做可以增加封装性.包裹弹性(packaging flexibility)和机能扩充性.
- Effective C++学习笔记 条款02:尽量以const,enum,inline替换 #define
尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...
- Effective C++_笔记_条款02_尽量以const、enum、inline替换#define
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 这个条款或许改为“宁可以编译器替换预处理器”比较好,因为或许#d ...
随机推荐
- Spring入门之HelloSpring
Spring描述: -轻量级:Spring是非侵入式的-基于Spring开发的应用中的对象可以不依赖于Spring的API -依赖注入(DI---dependency injection,IOC) - ...
- HDU 5319 Painter
题意:红色从左上向右下涂,蓝色从右上向左下涂,既涂红色又涂蓝色就变成绿色,问最少涂几下能变成给的图. 解法:模拟一下就好了,注意细节. 代码: #include<stdio.h> #inc ...
- tcxtreelist 展示图片 图像
procedure TfrmstPostImageCollate.LoadCollateImage(AOrderID: integer);var mySql: string; node: TcxTre ...
- PPTP VPN不能打开百度
问题: 在阿里云上设置PPTP VPN,电脑能正常连接,能打开京东 淘宝 QQ等没有问题,但是不能打开百度 糯米等网站.开始怀疑是代理设置问题,后面确认未设置独立规则. 1.从应用层看排除特殊规则设 ...
- HDU 3289 Cat VS Dog (二分匹配 求 最大独立集)
题意:每个人有喜欢的猫和不喜欢的狗.留下他喜欢的猫他就高心,否则不高心.问最后最多有几个人高心. 思路:二分图求最大匹配 #include<cstdio> #include<cstr ...
- C# 结构体保存自定义文件 实例部分代码(转)
http://www.cnblogs.com/jxsoft/archive/2011/08/26/2154705.html
- Discuz资料整理
1.截取字符串:messagecutstr(strip_tags($post['message']), 160);
- jquery chart plugin
jquery flot http://www.jqueryflottutorial.com/ jquery jqplot http://www.jqplot.com/ highcharts中文网 : ...
- HW6.7
public class Solution { public static void main(String[] args) { int[] count = new int[10]; int numb ...
- 荔枝FM架构师刘耀华:异地多活IDC机房架构 - 极客头条 - CSDN.NET
荔枝FM架构师刘耀华:异地多活IDC机房架构 - 极客头条 - CSDN.NET 荔枝FM架构师刘耀华:异地多活IDC机房架构 - 极客头条 - CSDN.NET 途牛谭俊青:多数据中心状态同步&am ...