杂项
1. operator
operator op= 直接作用于lvalue 并传回reference, 而 operator op 必须传回一个临时对象。
如果你提供某个op 的标准版本 operator op, 同时请为他提供一份 assignment 版本 operator op=, 并且用后者为基础来实现前者, 同时也请保存 op 和 op= 之间的自然关系。
使用以下准则来决定一个运算符是否为member function
1)一元运算符 应该是member function
2)= () [] 和 -〉必须是memeber
3)assignment 版的运算符 必须是member
4) 其他所有二元运算符都应该是non-member
总是让operator<< 和 operator>> 传回stream reference
prefix 运算符 应该传回reference to non-const, postfix 运算符应该传回一个const value
2. main 标准写法
int main(int argc, char* argv[])
3. 类型转换
4. const
const 函数:如果函数修改了对象的内部状态,但是修改对象的可见状态没有发生变化,那么他还是应该被声明为 const。
6. 嵌套类和局部类, 嵌套函数和局部函数
如果嵌套类被声明为public,那么任何外部代码都可以称之为OutClass::NestedClass,如果为private,那么只有OutClass的成员和友元才可以使用NestedClass。
局部类是定义在一个函数范围内的类,无论成员函数还是自由函数
局部类型,没有链接的类型、未命名的类型,以及从这些类型中的任何一个复合而成的类型都不能作为模板类型的参数的实参使用。
C++不支持嵌套函数和局部函数
7. 预处理宏
1)避免重复定义头文件
2)条件编译,获得可移植性
3)用#pragma 禁止掉无伤大雅的警告
8. using 使用规则
2)绝对不要在头文件中使用名字空间using声明
3)实现文件中,绝对不要在#include指令前使用using声明或using指令
4)在使用C头文件时,采用新风格的#include<cheader>
9. 尽量使用\n而不是endl
10. float 和double
11. operator new, operator delete
void * operator new(size_t size) // operator new还可能有其它参数
{
size = 1; // 把它当作1个字节请求来处理
}
while (1) {
分配size字节内存;
if (分配成功)
return (指向内存的指针);
// 分配不成功,找出当前出错处理函数
new_handler globalhandler = set_new_handler(0);
set_new_handler(globalhandler);
if (globalhandler) (*globalhandler)();
else throw std::bad_alloc();
}
}
非类成员形式的operator delete的伪代码:
void operator delete(void *rawmemory)
{
if (rawmemory == 0) return; file://如/果指针为空,返回
//
释放rawmemory指向的内存;
return;
}
一个设计得好的new-handler函数必须实现下面功能中的一种。
·产生更多的可用内存。这将使operator new下一次分配内存的尝试有可能获得成功。实施这一策略的一个方法是:在程序启动时分配一个大的内存块,然后在第一次调用new-handler时释放。释放时伴随着一些对用户的警告信息,如内存数量太少,下次请求可能会失败,除非又有更多的可用空间。
·安装另一个不同的new-handler函数。如果当前的new-handler函数不能产生更多的可用内存,可能它会知道另一个new-handler函数可以提供更多的资源。这样的话,当前的new-handler可以安装另一个new-handler来取代它(通过调用set_new_handler)。下一次operator new调用new-handler时,会使用最近安装的那个。(这一策略的另一个变通办法是让new-handler可以改变它自己的运行行为,那么下次调用时,它将做不同的事。方法是使new-handler可以修改那些影响它自身行为的静态或全局数据。)
·卸除new-handler。也就是传递空指针给set_new_handler。没有安装new-handler,operator new分配内存不成功时就会抛出一个标准的std::bad_alloc类型的异常。
·抛出std::bad_alloc或从std::bad_alloc继承的其他类型的异常。这样的异常不会被operator new捕捉,所以它们会被送到最初进行内存请求的地方。(抛出别的不同类型的异常会违反operator new异常规范。规范中的缺省行为是调用abort,所以new-handler要抛出一个异常时,一定要确信它是从std::bad_alloc继承来的。想更多地了解异常规范,参见条款m14。)
·没有返回。典型做法是调用abort或exit。abort/exit可以在标准c库中找到
12. 指针和引用
指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,以后不能改变。
13. 为什么内置数组类型不支持数组之间的赋值
14. 指针运算
例如: p++,p--,p+i,p-i,p+-i,p-=i等。
C++规定,一个指针变量加/减一个整数是将该指针变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数相加或相减。如p+i代表这样的地址计算: p+i*d,d为p所指向的变量单元所占用的字节数。这样才能保证p+i指向p下面的第i个元素。
(2) 两个指针变量可以相减
如果两个指针变量指向同一个数组的元素,则两个指针变量值之差是两个指针之间的元素个数,见图6.25。
假如p1指向a[1],p2指向a[4],则p2-p1=(a+4)-(a+1)=4-1=3。
但p1+p2并无实际意义。
15. (…)作为函数参数
16. 未命名名字空间
17.常量数组的operator[]
18.关于定义二维数组的问题
a[3][]={*,*,*……}。
首先你要理解二维数组的真正含义,它的第一维就是一组数据的起始地址,第二维就是某组数据中的某个值.其次,你要知道a[][4]所表达的意思,是指二维数组a的每一维都是由4个元素组成的一维数组.而编译器可以根据你赋给a的初值个数计算它的第一维长度(元素总个数/4,如果不能整除,则长度加1,此时还应该有几个没有赋初值的数组元素).而a[3][]的意思从表面上看可以成立,但问题是编译器不能直接识别其第二维的确切长度(你可以考虑,如果总的初值个数为2时,可以认为a的第二维长度为1,也可以是2,.......),这样就会产生错误.所以,可以a[][4]={*,*,*……}这样定义,而不能定义a[3][]={*,*,*……}。
函数参数也可以是多维数组,但是参数必须指明一维以外所有维的参数