C++函数的内存分配机制(转)2010-08-24 16:031.同一个类的对象共享同一个成员函数的地址空间,而每个对象有独立的成员变量地址空间,可以说成员函数是类拥有的,成员变量是对象拥有的2.非虚函数对于非虚函数的调用,编译器只根据数据类型翻译函数地址,判断调用的合法性,由1可知,这些非虚函数的地址与其对象的内存地址无关(只与该类的成员函数的地址空间相关),故对于一个父类的对象指针,调用非虚函数,不管是给他赋父类对象的指针还是子类对象的指针,他只会调用父类中的函数(只与数据类型(此为类类型)相关,与对象无关)。
3.虚函数虚拟函数的地址翻译取决于对象的内存地址,而不取决于数据类型(编译器对函数调用的合法性检查取决于数据类型)。
如果类定义了虚函数,该类及其派生类就要生成一张虚拟函数表,即vtable。
而在类的对象地址空间中存储一个该虚表的入口,占4个字节,这个入口地址是在构造对象时由编译器写入的。
所以,由于对象的内存空间包含了虚表入口,编译器能够由这个入口找到恰当的虚函数,这个函数的地址不再由数据类型决定了。
故对于一个父类的对象指针,调用虚拟函数,如果给他赋父类对象的指针,那么他就调用父类中的函数,如果给他赋子类对象的指针,他就调用子类中的函数(取决于对象的内存地址)。
虚函数需要注意的大概就是这些个地方了,之前在More effective C++上好像也有见过,不过这次在Visual C++权威剖析这本书中有了更直白的认识,这本书名字很牛逼,看看内容也就那么回事,感觉名不副实,不过说起来也是有其独到之处的,否则也没必要出这种书了。
4.如果类包含虚拟成员函数,则将此类的析构函数也定义为虚拟函数因为派生类对象往往由基类的指针引用,如果使用new操作符在堆中构造派生类对象,并将其地址赋给基类指针,那么最后要使用delete操作符删除这个基类指针(释放对象占用的堆栈)。
这时如果析构函数不是虚拟的,派生类的析构函数不会被调用,会产生内存泄露。
5.纯虚拟函数纯虚拟函数没有函数体,专为派生类提供重载的形式。
只要形象的将虚拟函数赋值为0,即定义了纯虚函数,例如void virtual XXXX(char* XXX) = 0;定义了纯虚函数的类称为抽象基类。
抽象基类节省了内存空间,但不能用来实例化对象。
其派生类必须重载所有的纯虚函数,否则产生编译错误。
抽象基类虽然不能实例化,为派生类提供一个框架。
抽象基类为了派生类提供了虚拟函数的重载形式,可以用抽象类的指针引用派生类的对象,这为虚拟函数的应用准备了必要条件。
C/C++中malloc和new区别2009-05-13 15:56:32 阅读(1132) 发表评论1,malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。
它们都可用于申请动态内存和释放内存。
2,对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。
对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。
由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free.3,因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete.注意new/delete不是库函数。
4,C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存new 是个操作符,和什么"+","-","="……有一样的地位。
malloc是个分配内存的函数,供你调用的。
new是保留字,不需要头文件支持。
malloc需要头文件库函数支持。
new 建立的是一个对象,malloc分配的是一块内存。
new建立的对象你可以把它当成一个普通的对象,用成员函数访问,不要直接访问它的地址空间malloc分配的是一块内存区域,就用指针访问好了,而且还可以在里面移动指针。
简而言之:new 是一个操作符,可以重载malloc是一个函数,可以覆盖new 初始化对象,调用对象的构造函数,对应的delete调用相应的析构函数malloc仅仅分配内存,free仅仅回收内存2010-07-18 16:34 609人阅读 (0) Effective item 12new 分配空间->初始化->构造函数malloc 分配空间对象的创建分两步:1. 数据成员初始化。
(参见条款13)2. 执行被调用构造函数体内的动作。
[cpp]1.class AA2.{3.public:4. string s;5.};6.int main()7.{8. AA *a = (AA *)malloc(sizeof(AA));9. a->s = "abc";10. system("pause");11.return 0;12.}由于a中的s未被初始化,也就是没有调用string的默认构造函数导致s->s = "abc"异常使用AA *a = new AA;正常运行[cpp]1.class AA2.{3.public:4. AA()5. {6. cout << "AA constructor" << endl;7. }8. ~AA()9. {10. cout << "AA destructor" << endl;11. }12. BB s;13.};14.int main()15.{16.//AA *a = (AA *)malloc(sizeof(AA));17.//free(a);18. AA *a = new AA;19.delete a;20. system("pause");21.return 0;22.}显示:BB constructor // 对AA类中成员的初始化过程AA constructor // 对AA构造函数的调用AA destructor // 对AA析构函数的调用BB destructor使用malloc无任何显示初始化列表与构造函数:初始化列表是复制构造函数的过程即Intialization (const 和引用数据只能初始化不可以赋值)(使用初始化列表的对象默认初始化过程不再进行)构造函数是赋值过程即assignment (赋值前已经有了一个默认初始化过程[调用他的默认构造函数] 然后在赋值操作效率比直接利用初始化列表低)在构造函数内对成员变量赋初值:[cpp]1.class BB2.{3.public:4. BB()5. {6. cout << "BB constructor" << endl;7. }8. BB(const BB& bv)9. {10. a = bv.a;11. cout << "BB copy constructor" << endl;12. }13. ~BB()14. {15. cout << "BB destructor" << endl;16. }17.const BB& operator=(const BB& bv)18. {19. a = bv.a;20. cout << "BB assignment" << endl;21.return *this;22. }23.int a;24.};25.class CC26.{27.public:28. CC()29. {30. cout << "CC constructor" << endl;31. }32. CC(const CC& cv)33. {34. a = cv.a;35. cout << "CC copy constructor" << endl;36. }37. ~CC()38. {39. cout << "CC destructor" << endl;40. }41.const CC& operator=(const CC& cv)42. {43. a = cv.a;44. cout << "CC assignment" << endl;45.return *this;46. }47.int a;48.};49.class AA50.{51.public:52. AA(const BB& bb,const CC& cc)53. {54. b = bb;55. c = cc;56. }57.//AA(const BB& bb,const CC& cc):b(bb), c(cc){}58. BB b;59. CC c;60.};61.int main()62.{63. BB b;64. CC c;65. AA *a = new AA(b, c);66.delete a;67. system("pause");68.return 0;69.}显示:BB constructor // main 中b的构造CC constructor // main 中c的构造BB constructor // 类AA对BB的默认初始化通过BB的默认构造函数CC constructor // 类AA对CC的默认初始化通过CC的默认构造函数BB assignment // 类AA构造函数中的赋值CC assignment // 类AA构造函数中的赋值CC destructorBB destructor在初始化列表中初始化[cpp]1.class BB2.{3.public:4. BB()5. {6. cout << "BB constructor" << endl;7. }8. BB(const BB& bv)9. {10. a = bv.a;11. cout << "BB copy constructor" << endl;12. }13. ~BB()14. {15. cout << "BB destructor" << endl;16. }17.const BB& operator=(const BB& bv)18. {19. a = bv.a;20. cout << "BB assignment" << endl;21.return *this;22. }23.int a;24.};25.class CC26.{27.public:28. CC()29. {30. cout << "CC constructor" << endl;31. }32. CC(const CC& cv)33. {34. a = cv.a;35. cout << "CC copy constructor" << endl;36. }37. ~CC()38. {39. cout << "CC destructor" << endl;40. }41.const CC& operator=(const CC& cv)42. {43. a = cv.a;44. cout << "CC assignment" << endl;45.return *this;46. }47.int a;48.};49.class AA50.{51.public:52.//AA(const BB& bb,const CC& cc)53.//{54.// b = bb;55.// c = cc;56.//}57. AA(const BB& bb,const CC& cc):b(bb), c(cc){}58. BB b;59. CC c;60.};61.int main()62.{63. BB b;64. CC c;65. AA *a = new AA(b, c);66.delete a;67. system("pause");68.return 0;69.}显示:BB constructor // main 中b的构造CC constructor // main 中c的构造BB copy constructor // 类AA对BB的初始化列表中的初始化通过BB的复制构造函数【省去了上例的默认初始化过程】CC copy constructor // 类AA对CC的初始化列表中的初始化通过CC的复制构造函数【省去了上例的默认初始化过程】CC destructorBB destructor。