A *pa=&a;
(pa->*pmf)(); //调用pa->func()
指向函数成员的指针要考虑多态性。所以,当你通过指针调用一个虚函数成员 时,这个调用将会被动态回收。另一个需要注意的地方,你不能取一个类的构造函 数和析构函数的地址。
要点7、避免产生内存碎片
经常会有这样的情况:你的应用程序每运行一次时就因为程序自身缺陷而产生 内存漏洞而泄漏内存,而你又在周期性地重复着你的程序,结果可想而知,它也会 使系统崩溃。但怎样做才能预防呢?首先,尽量少使用动态内存。在大多数情况 下,你可能使用静态或自动存储或者是STL容器。第二,尽量分配大块的内存而不 是一次只分配少量内存。举个例子:一次分配一个数组实例所需的内存,而不是一 次只分配一个数组元素的内存。
要点8、是delete还是delete[]
在程序员中有个荒诞的说法:使用delete来代替delete[]删除数组类型时是可 以的!
举个例子吧:
int *p=new int[10];
delete p; //错误,应该是:delete[] p
上面的程序是完全错误的。事实上,在一个平台上使用delete代替delete[]的 应用程序也许不会造成系统崩溃,但那纯粹是运气。你不能保证你的应用程序是不 是会在另一个编译器上编译,在另一个平台上运行,所以还是请使用delete[]。
要点9、优化成员的排列
一个类的大小可以被下面的方式改变:
struct A {
bool a; int b; bool c;
}; //sizeof (A) == 12
在我的电脑上sizeof (A) 等于12。这个结果可能会让你吃惊,因为A的成员总 数是6个字节:1+4+1个字节。那另6字节是哪儿来的?编译器在每个bool成员后面 都插入了3个填充字节以保证每个成员都是按4字节排列,以便分界。你可以减少A 的大小,通过以下方式:
struct B {
bool a; bool c; int b;
}; // sizeof (B) == 8
这一次,编译器只在成员c后插入了2个字节。因为b占了4个字节,所以就很自 然地把它当作一个字的形式排列,而a和c的大小1+1=2,再加上2个字节就刚好按两 个字的形式排列B。
要点10、为什么继承一个没有虚析构函数的类是危险的?
一个没有虚析构函数的类意味着不能做为一个基类。如std::string,
std::complex, 和 std::vector 都是这样的。为什么继承一个没有虚析构函数的
类是危险的?当你公有继承创建一个从基类继承的相关类时,指向新类对象中的指 针和引用实际上都指向了起源的对象。因为析构函数不是虚函数,所以当你delete 一个这样的类时,C++就不会调用析构函数链。举个例子说明:
class A {
public:
~A() // 不是虚函数 { // ... } };
class B: public A //错; A没有虚析构函数 {
public: ~B() { // ... } };
int main() {
A * p = new B; //看上去是对的
delete p; //错,B的析构函没有被调用 }
要点11、以友元类声明嵌套的类
当你以友元类声明一个嵌套的类时,把友元声明放在嵌套类声明的后面,而不 前面。
class A {
private: int i; public:
class B //嵌套类声明在前 {
public:
B(A & a) { a.i=0;}; };
friend class B;//友元类声明 };
如果你把友元类声明放在声明嵌套类的前面,编译器将抛弃友元类后的其它声 明。