《effective C++》总结【1】
最近开始看c++经典著作《effective c++》,总结了一些要点。
关键字的使用
1 自定义类的构造函数应该加上explicit,目的是为了防止隐式转换。除非有好的理由说明需要隐式转换,否则默认加上explict防止出现没有预料到的情况。
2 对于内置类型(int, double)和STL来说,pass-by-value比pass-by-reference更加高效,但是对于自定义的类,pass-by-reference比pass-by-value更加高效。
3 由于#define定义的宏常量可能没有进入到记号表,导致追踪不到。我是从来没遇到过这种情况,但是作者还是建议在众多场合不要使用#define。
- 定义常量整数或实数时,尽量用const int或const double代替。这会导致更少量的码。
- 定义常量指针时,要用两次const。const char* authorname = “scott meyers”。
- 定义类中的常量时,还要用static修饰。
- 定义类中的数组时,必须要定义常量,这时如果编译器不允许在类内声明时定义常数,就可以用enum代替。例如
class GamePlayer{
private:
enum { NumTurns = 5};
int scores[NumTurns];
}
enum的行为比较像#define而不像const。例如取一个enum的地址是不合法的,而取一个#define的地址通常也不合法。
- 用template inline函数代替#define函数
错误用法:#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
正确用法:template<typename T>
inline void callwithmax(const T&a, const T& b)
{
f(a > b ? a : b);
}
4 多用const关键字可帮助编译器侦测出错误用法。const语法虽然变化多端,但并不莫测高深。如果关键字const出现在星号左边,表示被指物是常量。如果const出现在星号右边,表示指针自身是常量。如果出现在星号两边,表示被指物和指针两者都是常量。
- const用于返回值,避免返回值被赋值。
class Rational {...};
const Rational operator*(const Rational& a, const Rational & b); 此处之所以要返回一个const对象是为了防止给返回值赋值这样的暴行,比如if( (a*b)=c)这样无意识的错误。
这样做可以保持与内置类型兼容。如果a和b都是内置类型,这样的代码直截了当就是不合法。因此自定义类型最好也保持这样。
- const用于成员函数,两个成员函数若只是常量属性不同,可以被重载(也就是说是两个不同的函数)。const成员函数只能更改const成员,而不能更改non-static成员变量。
如果要让const成员函数修改部分成员变量,可以使用mutable关键字来解禁。
为了避免const和non-const成员函数中代码重复,可以在non-const成员函数中调用const函数,反之不可。
class TextBlock{
public:
const char& operator[](size_t position) const
{
...
return text[position];
}
char & operator[](size_t position)
{
return const_cast(static_cast<const& TextBlock>(*this)[position]);
}
5 确定对象在调用之前已经被初始化了。
如果遇到一个全局对象A调用另一个全局对象B时,必须要保证B在A之前先被初始化了。
为了避免可能会忘记先后顺序的操作,可以将全局对象放进函数内(该对象在此函数内声明为static),并在函数内返回一个reference指向它所含的对象。
class FileSystem {...}
FileSystem& tfs()
{
static FileSystem fs; //定义并初始化fs
return fs;
}
class Directory {..};
Directory::Directory(params)
{
std::size_t disks = tfs().numDisks(); //调用FileSystem类
}
Directory & tempDir()
{
static Directory td; //定义并初始化对象
return td;
}
构造/析构/赋值
6 编译器会自动生成构造、析构、赋值等函数,但如果用户自定义了构造函数,则会覆盖原来的默认构造函数。
7 为了禁止拷贝等行为,可以将成员函数声明为private并不予实现。
8 任何class只要带有virtual函数都几乎确定应该也有一个virtual析构函数。如果class不含virtual函数,通常表示它并不意图被用做一个base class。当class不企图被当作base class,令其析构函数为virtual往往是个馊主意。
9 不建议继承标准容器或者带有非virtual析构函数的class。比如class SpecialString:public string是不建议的。因为string类内部不含有virtual函数,可能会导致未定义行为。
10 不要在析构函数中吐出异常。如果析构函数中需要调用可能抛出异常的函数,析构函数应该捕捉任何异常,然后吞下他们从而不让异常传播。如果客户需要对某个函数运行期间抛出的异常作出反应,那么class应该提供一个普通函数(而非在析构函数中)执行该操作。
11 在构造函数和析构函数中,都不应调用virtual函数。
12 当为派生类写拷贝构造函数或等号操作符时,要记得把基类也一并拷贝。
参考:《effective c++》
原文地址:https://www.cnblogs.com/corineru/p/11380388.html
- 设计模式专题(四)——代理模式
- Array数组函数(一)
- ASP.NET AJAX(5)__JavaScript原生类型以及Microsoft AJAX Library什么是Microsoft AJAX LibraryObject原生类型Object.pro
- 使用 Octave 来学习 Machine Learning(一)
- ASP.NET AJAX(4)__客户端访问WebService服务器端释放WebService方法客户端访问WebService客户端访问PageMethod错误处理复杂数据类型使用基础客户端代理的
- 讲真,你该做备份的有效性校验了
- memcache安装方法
- 设计模式专题(五)——工厂方法模式
- ASP.NET AJAX(11)__ScriptManagerUpdatePanel的支持成员功能控制成员脚本控件支持成员ScriptMode和ScriptPathLoadScriptsBeforeU
- SQL Server 2016新特性:动态数据屏蔽(DDM)
- ASP.NET AJAX(12)__浏览器兼容功能判断浏览器的类型和版本Sys.Browser针对DOM元素的兼容操作针对DOM事件的兼容操作
- 设计模式专题(六)——原型模式
- ASP.NET AJAX(13)__利用Microsoft AJAX Library开发客户端组件Sys.Component成员Sys.IDisposable成员Sys.INotifyDisposin
- 设计模式专题(七)——建造者模式
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- c++ int,unsigned int混合表达式类型转换
- MySQL5.7+查看Waiting for table metadata lock 锁情况
- input如何快速进行规则校验
- 史上最详细的sqlServer手工注入详解
- Spring 基于 Java 的配置
- Spring中的Spring JSR-250 注释之@Resource
- python 用opencv接口把视频逐帧转化为图片
- Element el-tree树形控件的数据处理方法
- 基于docker快速搭建hive环境
- flag区分大小写的sql盲注
- Spring中的Spring JSR-250 注释
- WebRTC 入门指南
- 【DB笔试面试844】在Oracle中,tnsnames.ora文件的作用是什么?
- Spring 基于注解(annotation)的配置之@Qualifier注解
- Spring 基于设值函数的依赖注入