C++编程指南

模板类

  用C++在编写规模稍大些的程序时,应该把类的声明和实现分开,这样可以提高编译效率。只要cpp文件没有改动,编译时编译器不会对该文件进行重新编译,也就是说代码已经被固化起来。
  模板类的就是根据变量类型的不同产生对应类型的基类代码。因为变量类型的不同,本质上的代码也就不同,所以模板类的代码是动态的。模板类需要在使用到的地方利用声明模板的typename或者class参数的时候,才会即时生成代码。那么当我把模板声明和实现分开的时候,这个即时过程因为编译器只能找到声明而找不到实现,所以在调用模板类的地方就会报错。
  所以在编写模板类的时候要将声明和实现统一写到头文件中。

虚函数

  C++中为了实现多态引入了virtual关键字,用该关键字声明的函数在调用时是动态链接而非静态链接。virtual可以声明虚函数和纯虚函数,虚函数的声明方式为:virtual 类型名 函数名();,纯虚函数的声明方式为:virtual 类型名 函数名() = 0;。两者的最大不同之处在于:虚函数可以在声明的类中实现;纯虚函数不可以在声明的类中实现,而且继承该类的派生类必须给出该纯虚函数的实现方法。
  无法被实例化的类被称为虚类。含有虚函数的类不一定是虚类,含有纯虚函数的类一定是虚类。使用C++的纯虚函数构造虚类可以实现Java中接口的相关功能。

析构函数

  派生类会继承基类的构造函数和析构函数,在实例化派生类时会先调用基类的构造函数再调用派生类的构造函数,而在销毁实例时会先调用派生类的析构函数再调用基类的析构函数。
  当一个基类指针指向一个派生类实例时,若基类析构函数声明为虚函数,delete基类指针,会先调用派生类的析构函数,再调用基类的析构函数。若基类析构函数没有声明为虚函数,delete基类指针,只会调用基类的析构函数,而不会调用派生类的析构函数,这样会造成销毁实例的不完全。
  所以一个基类或派生类没有虚析构函数编译器会发出警告。

优先队列

  优先队列不是一个容器类,它需要借助vector类或者queue类来实现。优先队列的定义方法为:priority_queue<变量类型,存储容器=vector<对应变量类型>,比较类=less<对应变量类型> >,存储容器缺省时默认使用vector,比较类缺省时默认使用less<对应变量类型>建立最大堆,可以传入greater<对应变量类型>类建立最小堆,也可以建立一个新类并在类中对()进行重载,然后将该类传入。主要函数有以下几个:
  empty();如果队列为空,则返回真
  pop();删除对顶元素,删除第一个元素
  push(value);加入一个元素
  size();返回优先队列中拥有的元素个数
  top();返回优先队列对顶元素,返回优先队列中有最高优先级的元素

  C++STL实现堆的方法是提供了堆操作的函数,这些函数作用在vector或queue实例或其它线性结构上来实现堆。这些函数被声明在algorithm头文件中。
  make_heap(begin,end,cmp=less);建堆函数
  push_heap(begin,end,cmp=less);压堆函数,将线性结构中最后一个元素当作需要压入的数据,所以若使用了vector做线性容器,需要先调用push_back()。
  pop_heap(begin,end,cmp=less);弹堆函数,将堆顶元素弹出并放到线性结构的最后一个位置,所以若使用了vector做线性容器,需要紧接着调用pop_back()完成弹堆。
  sort_heap(begin,end,cmp=less);堆排序函数
  四个函数的参数类型及意义相同,begin表示线性结构的头部指针或迭代器起始位置,end表示线性结构的尾部或迭代器结束位置,cmp是比较函数指针,该参数可缺省,缺省时默认调用less<对应变量类型>()函数建立最大堆,可以传入greater<对应变量类型>()函数建立最小堆,也可自行编写比较函数传入,也可利用Lambda表达式编写匿名函数传入。注意调用less<对应变量类型>()函数或greater<对应变量类型>()函数时一定要加上括号,less<对应变量类型>是一个类,less<对应变量类型>()是less<对应变量类型>类中重载()函数。

new

三种用法

plain new

  此方法在C++中的声明如下:

void *operator new(std::size_t)throw(std::bad_alloc);

  此方法为通常情况下的使用方法,在分配失败的情况下会抛出std::bad_alloc异常,而不会返回NULL。

nothrow new

  此方法在C++中的声明如下:

void *operator new(std::size_t, const std::nothrow_t &)throw();

  顾名思义,此方法为不抛出异常的方法,在分配失败的情况下会返回NULL,而不会抛出异常。
  使用方法举例:

int *a = new(nothrow) int;///nothrow new
delete a;
int *b = new(nothrow) int[32];///nothrow new
delete[] b;

placement new

  此方法在C++中的声明如下:

void *operator new(std::size_t, void *);

  此方法为在一块已经拥有的内存空间上来构造一个对象,在一个数组上构造或者在一块已分配的堆空间上等等。
  使用方法举例:

class test{
	int n;
public:
	test(int n):n(n){}
	~test(){}
}
int a[32];
int *b = new(a) test;///placement new
b->test::~test;///显式调用析构函数销毁对象

  此方法没有内存分配失败异常,因为该方法根本没有分配内存,只是在一块已有的内存空间上调用了构造函数。正是由于上述原因,使用此方法分配的内存空间也无需delete,如若使用了delete则可能会将原有的内存空间释放掉。当需要销毁对象时,无法使用delete销毁,应当显式调用析构函数销毁对象。

初始化

&esmp; 内置型变量new后跟()会分配空间并将空间内初始化为0,不跟()则仅分配空间不进行初始化。举例如下:

int *a = new int[32];///仅分配32个int的内存空间
int *b = new int[32]();///分配32个int的内存空间并将其全部初始化为0

  类型变量new后跟不跟()都会调用无参构造函数进行初始化。举例如下:

string *a = new string[32];///分配空间并为每个对象调用无参构造函数
string *b = new string[32]();///效果与上条语句相同
string *c = new string[32]("test");///编译器报错

map

insert

方法一:

map<string, int> a;
a.insert(pair<string, int>("test", 0));

方法二:

map<string, int> a;
a["test"] = 0;

find

探测某元素是否存在:

map<string, int> a;
if(a.find("test") != a.end()){
	cout << "Exist" << endl;
}

获取某元素的迭代器指针:

map<string, int> a;
itr = a.find("test");

二分查找

binary_search

查找某个元素是否出现

vector<int> a = {4, 3, 2, 1};
if(binary_search(a.begin(), a.end(), 3, greater<int>())==true){  /// 非升序排列需使用greater
	cout << "Exist" << endl;
}

lower_bound

查找第一个等于或大于某元素的位置

vector<int> a = {4, 3, 2, 1};
int i = lower_bound(a.begin(), a.end(), 3, greater<int>()) - a.begin();  /// 非升序排列需使用greater
cout << i << endl;

upper_bound

查找第一个大于某元素的位置

vector<int> a = {4, 3, 2, 1};
int i = upper_bound(a.begin(), a.end(), 3, greater<int>()) - a.begin();  /// 非升序排列需使用greater
cout << i << endl;
目 录 前 言6 第1 章 文件结构 1.1 版权和版本的声明. 1.2 头文件的结构. 1.3 定义文件的结构. 1.4 头文件的作用. 1.5 目录结构. 第2 章 程序的版式 2.1 空行. 2.2 代码行. 2.3 代码行内的空格. 2.4 对齐. 2.5 长行拆分. 2.6 修饰符的位置. 2.7 注释. 2.8 类的版式. 第3 章 命名规则 3.1 共性规则. 3.2 简单的WINDOWS 应用程序命名规则. 3.3 简单的UNIX 应用程序命名规则 第4 章 表达式和基本语句 4.1 运算符的优先级. 4.2 复合表达式. 4.3 IF 语句 4.4 循环语句的效率. 4.5 FOR 语句的循环控制变量. 4.6 SWITCH 语句. 4.7 GOTO 语句. 第5 章 常量 5.1 为什么需要常量. 5.2 CONST 与 #DEFINE 的比较. 5.3 常量定义规则. 5.4 类中的常量. 第6 章 函数设计 高质量C++/C 编程指南,v 1.0 2001 Page 4 of 101 6.1 参数的规则. 6.2 返回值的规则. 6.3 函数内部实现的规则. 6.4 其它建议. 6.5 使用断言. 6.6 引用与指针的比较. 第7 章 内存管理 7.1 内存分配方式 7.2 常见的内存错误及其对策 7.3 指针与数组的对比 7.4 指针参数是如何传递内存的? 7.5 FREE 和DELETE 把指针怎么啦? 7.6 动态内存会被自动释放吗?. 7.7 杜绝“野指针”. 7.8 有了MALLOC/FREE 为什么还要NEW/DELETE ?. 7.9 内存耗尽怎么办?. 7.10 MALLOC/FREE 的使用要点 7.11 NEW/DELETE 的使用要点. 7.12 一些心得体会 第8 章 C++函数的高级特性 8.1 函数重载的概念. 8.2 成员函数的重载、覆盖与隐藏. 8.3 参数的缺省值. 8.4 运算符重载. 8.5 函数内联. 8.6 一些心得体会. 第9 章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源. 9.2 构造函数的初始化表. 9.3 构造和析构的次序. 9.4 示例:类STRING 的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数. 9.6 示例:类STRING 的拷贝构造函数与赋值函数 9.7 偷懒的办法处理拷贝构造函数与赋值函数. 9.8 如何在派生类中实现类的基本函数. 9.9 一些心得体会. 第10 章 类的继承与组合. 高质量C++/C 编程指南,v 1.0 2001 Page 5 of 101 10.1 继承 10.2 组合 第11 章 其它编程经验. 11.1 使用CONST 提高函数的健壮性 11.2 提高程序的效率 11.3 一些有益的建议 参考文献 附录A :C++/C 代码审查表. 附录B :C++/C 试题. 附录C :C++/C 试题的答案与评分标准.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值