Effective C++ 45-48
45。弄清c++在幕后为你所写。所调用的函数。
假设设置一个空类,c++编译器会声明下面函数:拷贝构造函数。赋值运算符,析构函数,一对取地址运算符函数(const和非const)。而假设你没有声明不论什么构造函数的话,编译器会为你声明一个缺省构造函数。这些函数都是公有的。
编译器生成的缺省构造函数和析构函数实际上什么也不做。生成的析构函数通常是非虚构的,除非继承了一个具有虚析构函数的基类。缺省取地址符仅仅是返回对象的地址,即return this。而拷贝构造函数和赋值运算符,对类的非静态数据成员进行“以成员为单位”逐一拷贝构造或赋值,也就是浅拷贝。
当类中有引用时。默认的拷贝函数无法实现,编译器会报错,有常量也是。有指针是,会发生浅拷贝可是执行上没有错误。对于含有指针,引用和const成员的类须要自定义赋值运算符和复制构造函数。
而假设将派生类中的赋值运算符或拷贝构造函数声明为private,编译器也会拒绝为这个派生类生成对应的赋值运算符和拷贝构造函数。
46.宁可编译和链接时出错,也不要在执行时出错。
当通过编译和链接后,仅仅有极少数情况会让C++抛出异常。如内存耗尽,执行时错误和C++没什么关系。
C++没有执行时检測,要尽量避免执行时错误。
对于执行时错误。在一个执行中没有错误,并不表示其就是正确的了。由于每次程序执行的状态都不一样。
而避免执行时错误的一般方法是对设计做一些小小的修改,就能够在编译期间消除可能产生的执行时错误。一般设计在程序中添加新的数据类型,以在编译时检測数据的安全性。
对于一个日期类,有构造函数:Date(int day,int month,int year)。实现这个类面临的问题是对day和month进行合法性检測。假设不进行检測,因为其内部逻辑可能会导致一些执行时错误。
一种简单的方法是使用枚举
enum Month {Jan = 1,Feb = 2,....,Dec =12};
而构造函数改为:
Date(int day,Month month,int year);
可是这样做没有多大优点。由于枚举类型不用初始化,即直接 Date d(1,Month m,2014),能通过编译。可是执行时出错。
即想免除执行时检查,又要保证足够的安全性,选择使用一个类来实现month。
class Month{
public:
static const Month Jan(){return 1;}//这里事实上是调用隐式构造函数。事实上返回值为 Month(1);
//....
static const Month Dec(){return 12;}//使用静态函数。返回一个常量。防止任意修改
int toInt() const
{return number;}
private:
Month (int n):number(n){}
const int number;
};
这里调用类的静态成员返回相应的Month。而构造函数隐藏。防止用户自己去创建新的month。但即使有了这种类,用户还是能够指定一个非法的month,例如以下:
Month* m;
Data(1, *m ,2014);
消除全部的执行时检測是不切实际的。但将检查由执行时转移到编译或链接时一直值得努力的目标。这样做,会使程序更小,更快,更可靠。
47.确保非局部静态对象在使用前被初始化。
使用对象前一定要初始化。
非局部静态对象是指 : 定义在全局或名字命名空间内。或在一个类中被声明为static。或在一个文件范围内被定义为static。就是值所有的对象。去掉非静态 的局部变量 和函数内的静态变量。
当类依赖与这些非局部静态对象时,如在 一个文件里有一个全局对象theCountry, 在另外一个文件里有一个对象theCity。对city的初始化依赖与country的初始化。而程序的正确执行依赖于它们的初始化顺序。但确定非局部静态对象初始化的正确顺序非常困难,在多个编译单元中确保每一个这种对象初始化是非常困难的,尤其当程序变得更加复杂添加很多其它的这种非局部静态对象的情况下。
单一模式,将每一个非局部静态对象转移到函数中。声明其为static,其次,让函数返回这个对象的引用。这样用户就能够通过函数调用来指明对象,即用函数内部的static对象来代替非局部静态对象。由于对于函数的静态对象什么时候被初始化。c++明白的指出了。这种还有一个优点是假设这个模拟非局部静态对象从没被调用,也就永远没有对象构造和销毁的开销。简单的样例:
class country{....};
country& theCountry(){
static country tc;//定义和初始化theCountry
return tc;//返回它的引用。
}
48.重视编译器警告。
一般程序猿都会忽略编译器警告。毕竟没有出错。要理解编译器的各种警告的含义。书上举个样例:
class A{
public:
virtual void f() const{cout<<"fA";}
};
class B:public A{
public:
virtual void f(){cout<<"fB";}
};
书上说有编译器在这里会出一个 B::f() hides virtual A:::f()的错误,即A中声明的f函数并没有在B中又一次定义。可是被B中新声明的非const的f函数给隐藏了。可是这样没有实现多态。对于使用声明为A的指针的B的对象指向f函数的话,会调用A中的f函数。可是我用的vs2012中并没有提示这条警告。
Effective C++ 45-48的更多相关文章
- Effective C++ -----条款48:认识template元编程
Template metaprogramming(TMP,模板元编程)可将工作由运行期移往编译期,因而得以实现早期错误侦测和更高的执行效率. TMP可被用来生成“基于政策选择组合”(based on ...
- Effective Java 45 Minimize the scope of local variables
Principle The most powerful technique for minimizing the scope of a local variable is to declare it ...
- effective c++ Item 48 了解模板元编程
1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...
- 读书笔记 effective c++ Item 48 了解模板元编程
1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...
- Effective Java Index
Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...
- Effective Java 第三版——71. 避免不必要地使用检查异常
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- [转]python3之模块psutil系统性能信息
转自:https://www.cnblogs.com/zhangxinqi/p/9106265.html 阅读目录 1.psutil模块安装 2.获取CPU信息 3.内存信息 4.磁盘信息 5.网络信 ...
- 《Python自动化运维之路》 系统基础信息模块(一)
系统性能收集模块Psutil 目录: 系统性能信息模块psutil 系统性能信息模块psutil psutil能够轻松实现获取系统运行的进程和系统利用率包括(CPU,内存,磁盘 和网络)等.主要用于系 ...
- python3之模块psutil系统性能信息
psutil是个跨平台库,能够轻松实现获取系统运行的进程和系统利用率,包括CPU.内存.磁盘.网络等信息. 它主要应用于信息监控,分析和限制系统资源及进程的管理.它实现了同等命令命令行工具提供的功能, ...
- wazhu之agent功能详解
一.日志数据收集 日志数据收集是从服务器或设备生成的记录中收集的实时过程.此组件可以通过文本文件或Windows事件日志接收日志.它还可以通过远程syslog直接接收日志,这对防火墙和其他此类设备 ...
随机推荐
- BZOJ 4828 DP+BFS
被一道简单BFS坑了这么长时间我也是hhh了 //By SiriusRen #include <bits/stdc++.h> using namespace std; ,,):d(D),x ...
- ACM_百度的面试(单调栈)
百度的面试 Time Limit: 2000/1000ms (Java/Others) Problem Description: 在一个二维平面,从左到右竖立n根高度分别为:a[1],a[2],... ...
- 336 Palindrome Pairs 回文对
给定一组独特的单词, 找出在给定列表中不同 的索引对(i, j),使得关联的两个单词,例如:words[i] + words[j]形成回文.示例 1:给定 words = ["bat&quo ...
- Kafka的3节点集群详细启动步骤(Zookeeper是外装)
首先,声明,kafka集群是搭建在hadoop1.hadoop2和hadoop3机器上. kafka_2.10-0.8.1.1.tgz的1或3节点集群的下载.安装和配置(图文详细教程)绝对干货 如下分 ...
- Mysql(三):多表查询和存储程序
今天内容: ● 多表查询(内连接 外连接 子查询) ● 存储程序(存储过程 函数) 多表查询 同时从多张数据表中查取到需要的数据即是多表查询. 多表查询时,参与查询的表中每条数据进行组合,这种效果 ...
- hibernate.cfg.xml配置
hibernate.hbm2ddl.auto 配置: create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这 ...
- Android Activity作为dialog对话框的使用详细介绍
Activity做为Android应用层四大组件的重要组成部分,它的灵活性.可扩性无论是在应用还是游戏方面都得到了广泛应用,本文主要介绍Activity作为dialog对话框 的使用方法进行说明. 本 ...
- 程序员的幽默-献给所有Java程序员
1. 一程序员去面试,面试官问:“你毕业才两年,这三年工作经验是怎么来的?!”程序员答:“加班.” 2. 某程序员对书法十分感兴趣,退休后决定在这方面有所建树.于是花重金购买了上等的文房四宝.一日,饭 ...
- 检索COM类工厂中CLSID 为 {000209FF-0000-0000-C000-000000000046}的组件时失败, 原因是出现以下错误: 80070005
主要问题原因是Word权限配置问题 解决方案: 控制面板-管理工具-组件服务-计算机-我的电脑-DCOM配置 在列表中找到microsoft word97-2003 document 右键选择属性,选 ...
- (转)分布式文件存储FastDFS(二)FastDFS安装
http://blog.csdn.net/xingjiarong/article/details/50559761 在前面的一篇中,我们分析了FastDFS的架构,知道了FastDFS是由客户端,跟踪 ...