C++标准程序库
1. 如果要把一个template中的某个标识符号指定为一种型别,就算意图显而易见,关键字typename也不可或缺,因此一般的规则是,除了以typename修饰之外,template内的任何标识符号都被视为一个值而非一个型别.
2. 类的成员函数可以是个template,但这样的成员函数既不能是virtual也不能有缺省参数.
3. 如果程序允许我们为成员函数提供不同的template型别,就可以放宽”必须精确吻合”这条规则:只要型别可被赋值,就可以被当做上述成员模板函数的参数.
4. 通过explicit,我们可以禁止”单参数构造函数”,被用于自动类型转换.其中有对应的一个词implicit.这个词不是C++关键字(因为C++ 默认的是隐式转换的).这里这总结类似的关键字: volatile.使用这个关键字以后,优化器在用到这个变量时必须每次都小心的重新读取这个变量的值,而不是使用保存在寄存器中的备份.
5. auto_ptr中拥有权的转移情况:
◆ 某函数是数据的终点.
Voidskin(std::auto_ptr<ClassA>);
◆ 某函数是数据的起点
此外,不能以by reference方式传递auto_ptr.(无法预知拥有权是否被转交)
就特性而言,constauto_ptr类似于常数指针(T*const p).而非指向常数d的指针.(const T* p)
如果auto_ptr在整个生命期内都不必改变其所指对象的拥有权,就可以使用const auto_ptr
const std::auto_ptr<int> p(new int(42));
std::auto_ptr<int> q(new int( -11 ));
*p = *q;//此时只是q指向了新的地址.所有权并没有通过q转移.
6. const 成员函数.其对象的成员不能改变.
因此不难得出以下结论:
◆const 成员函数即可以供const对象调用,也能供非const对象调用,此时const不能改变非const对象的成员
◆ const 对象不能调用非const 成员函数(因为非const对象可能会改变const对象)
◆非const函数不能调用const函数,反之可行
Mutable关键字:在const成员函数中也能改变mutable修饰的变量
7. 前置式递增(++pos)与后置递增相比,前者效率高.因为需要额外的临时对象.所以,在一般情况下使用前置
8. 在使用set和map时,要注意排序问题.(关联容器)它们的实现是以树作为基本结构来存储.
9. 三类插入迭代器:
◆ back inserter:利用push_back操作向容器插入.适合的容器:vector,deque,list
◆ front insert:利用push_front操作向容器插入.适合的容器:deque,list.(相当于链表前插)
◆ general insert:向第二个参数的位置前插入新的元素.
Inserter(contain,contain.begin()) 相当于front_insert
Inserter(contain,contain.end()) 相当于back_insert
10. 更易型算法(remove,resort,modify)不能作用于关联式容器,因此时会改变某位置上的”值”(指键值).另外在选用算法的同时,首先应当确定是否可以利用容器的成员函数来代替.
11. 如果要把一个template中的某个标示符指定为一种类型,就算意图显而易见,关键字typename也不可或缺,因此C++的一般规则是,处理以type修饰之外,template内的任何标示符都被视为一个值,而非一个型别.
举例:
class A
{
public:
typedef int SubType;
private:
intvalue;
};
template<class T>
class MyClass{
typedef T::SubType * ptr;
// typedef typename T::SubType * ptr;
};
int main()
{
MyClass<A> my_cls;
}
编译器(vs2010)报错: error C2143: 语法错误 : 缺少“;”(在“*”的前面).
编译器好像并不认识SubType.这就是上面所说的把其当做为一个值,而非类型.加上typename就ok了.
11. STL容器元素必须满足的三个基本要求:
◆ 必须可透过copy构造函数进行复制.
◆ 必须可以透过assignment操作符完成赋值动作.
◆ 必须可以透过析构函数完成销毁动作.
解释一点:我们平日里经常会写一个类的容器,但是,类里面没有看到什么copy,assignment什么的.为什么程序还能正常运行?
举例:
#include <iostream>
#include <set>
using namespace std;
class A
{
public:
A(intiVlaue ):m_iValue( iVlaue ){}
private:
intm_iValue;
};
int main()
{
set<A> coll;
system("pause");
return0;
}
关键在于编译器会在这种情况下帮我们合成自己的赋值和复制操作.
其他的需要满足特殊情况的条件:
◆ 对顺序容器,元素的默认构造函数必须可用
◆ 对于某些特殊动作,必须定义operator==以执行相等的测试.
◆ 在关联容器中,元素必须定义排序准则,这里主要是定义<.
12. C++标准库对STL做出如下保证:
◆ 所有以节点来实现基础的容器(list,set,multiset,map,multimap),如果及诶单构造失败,容器保持不变.移除节点的容器保持不会失败.然而如果是对关联式容器插入多个元素,为保证已序性,失败时无法完全恢复原状.对插入单一元素操作,支持要么成功,要么原先的容器不受任何影响.此外,所有擦除操作(无论数量多少)肯定成功.
对list,就算插入多个元素,也属于安全操作,实际上,处理remove,remove_if,merge,sort,unique之外,要么成功,要么不受任何影响.
◆ 所有以array为构造基础的容器如vector,deque安插元素如果失败,都无法做到完全恢复.如果元素的型别保证拷贝动作不抛异常,则所有加诸于改元素身上的操作都能够保证要么成功,要么就毫无影响.