《Effective C++》笔记:开篇

老早就读过这本书了,在实验室当工具书查阅用,一直都没空来总结.趁这几天空闲就把知识巩固一下,也当复习了

导读(P3)内容:C++里声明、定义、初始化是什么?

这东西在面试题几乎是喜闻乐见的。

声明

即表明变量的名称和类型,声明就是告诉编译器某个东西的名称和类型。

学过编译原理知道符号表这个东西,在词法分析的时候会把解析声明的变量及函数。

特别是函数的重载,声明时会给这个函数赋上另一个名称,如void fun(int)和void fun(int,int),编译器可能会弄这样两个名字fun_i1,fun_i2.用以识别具体调用哪一个函数。

定义

书中表明,定义是补充声明遗漏的细节,也是编译器为对象分配内存的地点。

我的理解是声明只告诉了编译器名称和类型,具体内容未知,而定义则把这部分内容完善,定义提供的代码列出函数的功能,类的成员,

编译器为函数、类分配内存地址。

初始化

即给对象赋初值,对用户自定义类型的对象而言,初始化由构造函数执行。C++的默认构造函数要不没有任何参数,要不就是每个参数都有缺省值。

概念性的东西差不多就这样,那么让我们来实战一下。

  View Code

代码中的声明的是全局变量,全局变量与局部变量的声明与定义,在内存方面有差异,这部分在内存管理章节再提。

初始化中的explicit关键字

把对象的构造函数声明为explicit,可以阻止该对象进行隐式类型转换。什么是隐式类型转换?看如下代码

  View Code

如代码所示,fun需要的是一个类型为A的参数,传入int类型的参数编译运行成功,但实际上这样转换的隐患很大,在上述代码中编译器自作主张用28构造了一个新对象传给函数,打印对象的地址可以知道,虽然传入数值相同,

但跟原来的对象并不是一个东西,如果需要对该对象进行一些操作进行了隐式类型转换,结果必然与预料中不一致。

把代码中反注释一下并注释 - 行,即把单参数的构造函数声明为explicit,这时候调用fun(28)编译器会报错显示没有int到A的转换,此时调用fun(a)才能正确编译运行。

对象的Copy

C++中,如果在类中没有显式地声明一个copy构造函数,那么,编译器将会自动生成一个默认的copy构造函数,该构造函数完成对象之间的位拷贝。

下面举例说明copy构造函数的工作过程

  View Code

输出如下

QQ截图20140904055207

其中Widget w3 = w2,与w1 = w2不同,分别是copy构造和copy赋值,这是因为一个新对象被定义,一定会有一个构造函数被调用,不可能调用赋值操作。而前者有新对象被定义,后者没有,所以造成copy调用的区别。

把w1作为参数传入fun的时候,这里是以值传递的方式传给fun的,因此在调用的同时,fun会自己动调用copy构造函数把w1复制到w这个临时副本里,造成效率下降,这往往与设计者的初衷相违背。因此,书中的条款20:Pass-by-reference-to-const详细介绍了值传递与址传递的优劣,这个以后再说。

关于拷贝,自然免不了有浅拷贝和深拷贝之分。编译器生成的默认复制构造函数是浅拷贝,因此自定义复制构造函数覆盖默认复制构造函数是良好的编程风格,可以避免错误的产生,提高代码效率。这在条款5:Know what functions C++ silently writes and calls和条款6:Explicitly disallow the use of compiler-generated functions you do now want中有详细介绍。

 

OK,导读部分大概就是这么多知识。博客写得少,措词有点捉急啊,不过自己的理解总比直接把书中的原话打上来好。写这点字就这么费劲,感觉对不起以前教育我的语文老师~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值