本节知识点:
1.malloc与free和new与delete的区别:
a.malloc和free是 库函数,以 字节为单位申请堆内存 b.new和delete是 关键字,以 类型为单位申请堆内存 c.malloc和free是单纯的对内存进行申请与释放,不负责初始化,对于基本类型new关键字可以选择对内存进行初始化也可以不初始化 d. 对于类类型new和delete还负责调用构造函数和析构函数的调用 示例代码:#include#include using namespace std; class test { private: int a; int b; public: int c; test(int a, int b) { this->a = a; this->b = b; c = 9; cout << "a is "<< a < (malloc(sizeof(test))); //使用malloc 不调用构造函数 cout << "q is " << q->c < c < 2.编译器对构造函数的调用:
a.一般类给对象进行初始化的方式有三种,test> b.test t1(5)是最简单直接的,他强制编译器直接调用test类的构造函数( explicit无效)。test t2 = 5有四个步骤,第一,默认情况下,字面量5的类型为int,因此5无法直接用于初始化test对象,第二,但是编译器在默认情况下可以自动调用构造函数( explicit有效),第三,于是编译器尝试调用test(int)生成一个临时对象,第四,最后调用拷贝构造函数test(const test& obj) 用临时对象给t2进行初始化( explicit有效)。test t3 = test(5) 则是首先,手动调用test(int)构造函数( explicit无效),最后,编译器默认自动调用拷贝构造函数( explicit有效) c.c++编译器会尝试各种手段让程序通过编译: 方式一:尽力匹配重载函数 方式二:尽力使用函数的默认参数 方式三:尽力尝试调用构造函数进行类型转换 d. 利用explicit关键字阻止编译器对构造函数的调用尝试,代码如下:#includeusing namespace std; class test { private: int a; public: //explicit test(int c) { cout << "test()" < >
3.单例模式:
a.单例模式是 类的静态成员的一个很好的应用,单例模式适用于 一个类只允许产生一个对象的情况 b. 分析下单例模式:既然这个类仅仅只能产生一个对象的话,所以 这个类的构造函数就应该是private属性的,创建这类就不能是使用test t1(5)这样的语句了,就 只能使用函数(有两种, 一种是静态成员函数, 另一种是使用全局函数,这里面那个返回地址的变量也得是全局变量了 最好不要使用,因为这样就破坏了类的封装),成员函数不可以的原因是: 没有对象无法调用成员函数。函数中使用 new关键字,new这个类,然后 将new出来的新地址返回,这里面就需要一个static的静态成员变量来保存这个地址, 在这种情况下必须使用静态成员变量,因为这个变量即 要在类中使用(应该定义在类的前面或类中),而且这个变量的类型 还是这个类的类型或指针类型(应该定义在类的后面或类中), 要返回给其他函数使用这个变量应该是静态类型的(static属性)。所以说,在满足上面三种情况下,就要使用静态成员变量!!! 示例代码:#includeusing namespace std; class test { private: static test* tp; test() { } public: static test* creat() { if(NULL == tp) { cout << "hello" < 4.函数对象的实现:
a.无状态函数:函数的调用只与实参值相关 b.状态函数:函数的调用结果不仅与实参值相关还与之前的函数调用有关,就是有记忆功能的函数,其实就是利用static属性变量 示例代码:#include#include using namespace std; int fib1(int i) { int a1 = 0; int a2 = 1; int ret = a2; while( i > 1) { ret = a2 + a1; a1 = a2; a2 = ret; i--; } return ret; } int fib2() { static int a1 = 0; static int a2 = 1; int ret = a2; int t = a2; a2 = a2 + a1; a1 = t; return ret; } int main(int argc, char *argv[]) { for(int i=1; i<=10; i++) { cout< 注意:第一,fib1是以无状态函数的方式实现的,求解数列每一项时都会做重复的循环,时间复杂度为O(n) 第二,fib2是以状态函数的方式实现的,每调用一次就可以得到数列当前项的值,时间复杂度为O(1), 但是无法从头再来 c. 函数对象的实现:其实就是利用对象来模拟有状态函数,利用对象中的成员变量来代替static属性的变量,但是同样也不能回头,代码如下: #include#include using namespace std; int fib1(int i) { int a1 = 0; int a2 = 1; int ret = a2; while( i > 1) { ret = a2 + a1; a1 = a2; a2 = ret; i--; } return ret; } int fib2() { static int a1 = 0; static int a2 = 1; int ret = a2; int t = a2; a2 = a2 + a1; a1 = t; return ret; } class Fib { private: int a1; int a2; public: Fib() { a1 = 0; a2 = 1; } int operator() () { int ret = a2; int t = a2; a2 = a2 + a1; a1 = t; return ret; } }; int main(int argc, char *argv[]) { cout<<"int fib1(int i)"<