*转载请注明出处,请勿用于商业
1.strcpy()是碰到\0就会停止拷贝的,最好使用memcpy和strncpy代替。
2.memset并不分配内存,malloc才分配。3.循环里面要注意出错的地方sleep
4.匈牙利命名法
5.临时变量也要有意义
6.句柄要注意释放,特别是在出错的地方
7.memset不能过于频繁
8.对象的方法在前面,特别是public方法
9.使用extern C编译C++程序时,不能包含重载函数。因为C编译时函数名要唯一确定。
10.如果类的成员函数要调用全局函数,应加上::标志
11.不能在类中初始化常量,因为类的对象未被创建,编译器不知道SIZE的值是什么。
class A
{
const int SIZE = 100; //错误
int array[SIZE]; //错误
}
在类中建立常量的方法——使用枚举常量
class A
{
enum {SIZE1 = 100, SIZE2 = 200};
int array[SIZE1];
}
枚举常量不会占用对象空间,他在编译时被全部求值。枚举常量的缺点是:隐含类型是整数,最大值有限,且不能表示浮点数。
12.内存错误使用——释放了内存却继续使用它
有三种情况:
a. 对象调用关系过于复杂,难以搞清某个对象是否已经释放
b. return语句写错了,不能反悔指令“栈内存”的“指针”或“引用”,因为该内存在函数体结束时自动销毁
c. free或delete之后,没有将指针设置为NULL,导致产生“野指针”
13.字符数组和字符指针
char a[] = "hello";
char *p = a; //a的地址付给p,这样修改p就是修改a
sizeof(a); //结果:6,数组的大小
strlen(a); //结果:5,字符串长度
sizeof(p); //结果:4,指针大小
注意:数组作为参数传递时自动退化为同类型的指针。
void Func(char a[100])
{
cout<<sizeof(a)<<endl; //结果:4
}
14.指针的特性
(1)指针消亡了,并不表示它所指的内存会被自动释放
(2)内存被释放了,并不表示指针会消亡或者成了NULL指针
15.“野指针”的成因
(1)指针变量没有被初始化,任何指针变量被创建时不会自动成为NULL指针,它的缺省值是随机的
会乱指一气。所以要么初始化,要么指向NULL。
(2)free后没有置为NULL
(3)指针操作超越了变量的作用范围
16.exit和return
17.不要轻视拷贝构造函数与赋值函数
(1) 如果不主动编写构造函数和赋值函数,编译器将以“位拷贝”的方式自动生成缺省的函数。倘若类中含有指针变量,那么这两个缺省函数就隐含了错误。
如类String的两个对象a,b为例,假设a.m_data为“hello”,b.m_data为“world”。执行b.m_data=a.m_data将造成三个错误:1.b.m_data原有的内存没有被释放,造成内存泄露;2.b.m_data和a.m_data指向同一块内存;2.对象被析构时,m_data被释放了两次。
(2)拷贝构造函数和赋值函数,拷贝构造函数是在对象被创建时调用的,赋值函数只能被已经存在的对象调用。
String c = a; //调用了拷贝构造函数,最好写成才c(a)
c = b; //调用了赋值函数
NOTE:引用不可能为空,而“指针”可以为NULL
(3)如果不想写拷贝和赋值函数,就声明为私有方法:
class A
{
private:
A(const A &a);
A & operator = (const A &a);
}
18.派生类
(1)派生类的构造函数应在其初始化表里调用基类的构造函数
(2)基类与派生类的析构函数应该为虚函数,这样多态才有意义
(3)在编写派生类的赋值函数时,不要忘记对基类函数的数据成员重新赋值
Derived & Derived::operator = (const Derived &other)
{
//(2)对基类的数据成员重新赋值
Base::operate =(other); // 因为不能直接操作私有数据成员
}
19.继承
继承规则:若在逻辑上B是A的“一种”,并且A的所有功能和属性对B而言都有意义,则允许B继承A的功能和属性。