effective c++ 笔记 (3-4)
//---------------------------15/03/26----------------------------
3:const函数的哲学思辨:就当是科普知识吧!如果成员函数是const意味着什么?
这里有两个流行的概念:
1>bitwise(按位) constness(const + ness ==const的名词)又称physical constness
这个阵营的人相信,只有不改变对象的任何一个bit的函数才可以称为const函数,但是很多成员函数
并不具备const性质却能通过bitwise测试。
class CTextBlock
{
public:
...
char& oprator[](std::size_t position) const
{ return pText[position];}
private:
char* pText;
};
这个class不适当地将其operator[]声明为const函数,
而该函数却返回了一个reference指向对象内部值,
下面的代码可以很容易修改对象值
const CTextBlock cctb("hello");
char* pc = &cctb[0];
*pc = 'J';
上面的代码并没有出错,而且成功更改了对象的pText指针指向的内容
//总结:bitwise派别认为只要 const成员函数自己不改变对象的内容就算const
//至于通过我返回的返回值更改我的内容,那就没意见了
2>logical constness。这一派主张,一个const成员函数可以修改它所处理的对象内的某些bits,
但只有在客户端侦测不出的情况才得如此。如下
class CTextBlock
{
public:
std::size_t length() const;
private:
char* pText;
std::size_t textLength;
bool lengthIsValid;
};
std::size_t CTextBlock::length() const
{
if(!lengthIsValid)
{
textLength = std::strlen(pText);
lengthIsValid = true;
}
return textLength;
}
上面对textLength
和 lengthIsValid 的赋值都是错误的,因为在const成员函数中不能给它们赋值
所以应该在这两个变量的声明前加上mutable
小总结:本书也没有说出logical constness的意义在哪里,本来我看到logical的理解是,严格意义上
的“const”也就是不能修改对象,也不能返回
能修改对象的引用或指针。没想到logical竟然是允许修改
客户端侦测不到情况下的对象变量。
4:在const和non_const成员函数中避免重复
当一个成员函数很长时,const版本和non_const版本的成员函数会有很多重复的内容:
class TextBlock
{
public:
const char& operator[] (std::size_t position) const
{
... //边界检验
... //日志记录访问
... //检验数据完整性
return text[position];
}
char& operator[] (std::size_t position)
{
... //边界检验
... //日志记录访问
... //检验数据完整性
return text[position];
}
private:
std::string text;
};
上面的代码有很多重复的地方,所以我们要实现operator[]的机能一次,然后使用两次。也就是让其中一个
调用另外一个。
由于会进行状态的改变从const转到non_const或者反向转化,所以不能使用const版本调用non_const版本
因为const版本承诺不改变状态,所以就要使用non_const版本调用const版本,通过static_cast和
const_cast进行转化。
class TextBlock
{
public:
const char& operator[] (std::size_t position) const
{
... //边界检验
... //日志记录访问
... //检验数据完整性
return text[position];
}
char& operator[] (std::size_t position)
{
return const_cast<char&>(
static_cast<const TextBlock>(*this)
[position]
}
private:
std::string text;
};
上面const_cast的目的是为了去除const属性,static_cast的目的是为了正确调用const版本的operator[]
成员函数,不然就会无限调用本身,陷入死循环。
*/
}
//#4 确定对象呗使用前已经被初始化
{
/*
关于这点相信很多人都吃过苦头,但是还是常常会忘记
来自c的部分一般都不保证其内容被默认初始化就像数组(array)
而来自非c的部分一般都保证了初始化,就像vector。
最好的处理就是,对所有的对象在使用前都初始化。
1:关于构造函数的赋值和初始化:
构造函数在函数名后面加 : 然后跟上初始化内容,这样写就是初始化,而且比赋值效率高
如果写在{}中,那样就是赋值了,看一下例子
ABEntry::ABEntry(const std::string& name,
const std::string& address):theName(name)
{
theAddress=address;
}
theName就是初始化,theAddress就是赋值。前者效率更高,这是因为在调用构造函数的
时候,会为theName和 theAddress设置初始值,如果不是在初始化就设置而是在之后
更改,效率自然就低了.
2:一般来说最好都适用成员初值表来给定初始值。但是也有一种情况就是,一个类存在很多
构造函数,每个构造函数都需要初始化成员变量,那么为了减少工作量,也可以使用某个函数
来给定“初始值”其实就是赋值了。
3:这里讲了很重要的点,成员初始化次序,(之前的腾讯在线笔试题刚好做到了),成员初始化
次序总是相同的,base classes更早于其derived classes被初始化,而class的成员变量
总是以其声明次序被初始化。总结来说次序是这样的root class(继承中的最老的那个类)按声明
次序初始化成员变量,root class的子类按顺序...
自己这个类按声明次序初始化成员变量
所以在列成员初值表时,最好按声明顺序列出
4:不同编译单元内定义的non_local static对象的
初始化次序
static对象的寿命从被构造出来直到程序结束为止,这种对象包括global对象,定义与namespace
内的对象,在class内,函数内,以及在file作用域内被声明为static的对象
如果我们要使用这些对象,初始化次序就显得很重要:
class Directory
{
public:
Directory(params);
};
Directory::Directory( params)
{
std::size_t disks = tfs.numDisks();
}
Directory tempDir(params);
上面的tfs是一个non_local static对象
这时tfs就必须要先于tempDir被初始化,不然tfs都还没初始化就拿来用会发生不可预期的问题;
我们可以采用单例模式来解决这个问题:
class FileSystem{...};
FileSystem& tfs()
{
static FileSystem fs;
return fs;
}
有了这个函数,当需要使用FileSystem对象时,只要调用tfs()就可以了
上面的构造函数可以改成 std::size_t disks = tfs().numDisks();
有了tfs函数,当需要使用时就会先初始化tfs对象然后返回。
补充,单例模式应该写成如下形式:
class FileSystem
{
...
private:
Filesystem(){}; //让构造函数为私有的,这样才能保证单例
};
FileSystem& tfs()
{
static FileSystem* fs;
if(fs == NULL)
fs= new FileSystem;
return fs;
//加上if判断是为了懒加载,到了用的时候再创建出这个对象,不然会浪费内存
}
总结:采用non_const static对象不管是local还是non_lacol在多线程下都不安全
方法有两个:
1>在单线程时手动调用tfs()
2>使用互斥锁来加解锁;
*/
}
effective c++ 笔记 (3-4)的更多相关文章
- Effective Java笔记一 创建和销毁对象
Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第3章:使用函数--个人总结
前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- java effective 读书笔记
java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...
- Effective STL 笔记 -- Item 6 ~ 7: Container and Object Pointer
Effective STL 笔记 – Item 6 ~ 7: Container and Object Pointer 中间两次笔记被删掉了,简单补一下: Item 3 中提到如果将对象直接放入容器中 ...
- Item 5:那些被C++默默地声明和调用的函数 Effective C++笔记
Item 5: Know what functions C++ silently writes and calls 在C++中,编译器会自己主动生成一些你没有显式定义的函数,它们包含:构造函数.析构函 ...
- effective c++ 笔记 (1-3)
// // effective c++.cpp // 笔记 // // Created by fam on 15/3/23. // // //-------------------------- ...
随机推荐
- SQL Server存储过程输入参数使用表值
转载自:http://blog.csdn.net/smithliu328/article/details/9996149 在2008之前如果我们想要将表作为输入参数传递给SQL Server存储过程使 ...
- [SQLSERVER] 把TransactionLog截断
注意:以下语句非常危险 --BACKUP LOG MyDb TO DISK=’NUL:’
- SQL Server 从2000复制数据到2008及以上版本的一种方法
1.通过Linked Servers 执行sql出现错误提示,无法执行复制数据操作. sql: insert into tb_User select from [**.**.*.**].DB.dbo. ...
- LabVIEW TCP/IP 断开重连问题
LabVIEW的TCP/IP函数库非常好用,但是不恰当地设置打开连接结点的参数将带来一些问题,麻烦.如下图的打开连接的参数设置: 上图中指定了本地的端口,会发生这样的情况.当我们关闭应用程序之后,连接 ...
- 跨平台开发 -- C# 使用 C/C++ 生成的动态链接库
操作环境:Visual Studio 2017 如何实现 使用 C# 进行嵌入式开发? .NET Core 虽然实现了跨平台,但是不可能处处使用 C# 开发,就好像没人使用SQL开发安卓APP,每种语 ...
- 用JS制作《飞机大作战》游戏_第1讲(素材查找和界面框架搭建)-陈远波
一.查找素材: 二.分析游戏界面框架: 登录界面.游戏界面.暂停游戏界面.玩家死亡后弹出界面:并对应的界面包含什么元素: 三.分别搭建以上四个界面: 1.登录界面与游戏界面框架(隐藏游戏界面,四个界面 ...
- NOIP2018考前抱佛脚——图论基础复习
目录 存图方式 邻接矩阵存图 邻接表存图 链式前向星 最小生成树 例1 P1536 村村通 题目描述 输入输出格式 输入输出样例 标程 例2 P1546 最短网络 Agri-Net 题目背景 题目描述 ...
- php linux 环境搭建
Apache源于NCSAhttpd服务器,经过多次修改,成为世界上最流行的Web服务器软件之一.Apache取自“a patchy server”的读音,意思是充满补丁的服务器,因为它是自由软件,所以 ...
- 微信发红包 PHP 实现
最近做生日营销,需要微信发红包,特此从网上找了一篇教程 首先你的有个服务号,并且开通了微信支付,我在这就不说怎么去申请和开通了,我是看了微信官方文档后,想看官方文档的朋友可以到下面这个链接 https ...
- ElasticSearch + Logstash + Kibana 搭建笔记
ElasticSearch 安装 1.下载 ElasticSearch,本文使用的版本为 5.5.1. 2.配置 path.data: /data/es #数据路径 path.logs: /data/ ...