1.为什么C语言已经有malloc/free,C++也可以用,但是还需要new/delete.
1.针对内置类型用new还是malloc都是一样的
2.针对自定义类型,new还要调用构造函数完成初始化,delete还要调用析构函数完成清理
结论:C++中建议使用new/delete
//C
struct ListNode
{
int _val;
struct ListNode* _next;
struct ListNode* _prev;
};
typedef struct ListNode ListNode;
ListNode* BuyListNode(int val)
{
ListNode* node_c = (ListNode*)malloc(sizeof( ListNode));
node_c->_val = 1;
node_c->_prev = NULL;
node_c->_next = NULL;
return node_c;
}
void DeatoryListNode(ListNode* node)
{
}
int main()
{
int* p1 = (int*)malloc(sizeof(int));
int* p2 = new int;
ListNode* node1 = BuyListNode(1);
ListNode* node2 = BuyListNode(2);
ListNode* node3 = BuyListNode(3);
return 0;
}
C++
struct ListNode_CPP
{
int _val;
struct ListNode_CPP* _next;//兼容C strruct的用法
ListNode_CPP* _prev; //在CPP中,struct已经可以认为是类
ListNode_CPP(int val = 0)
:_val(val)
, _next(nullptr)
, _prev(nullptr)
{
cout << "ListNode_CPP(int val = 0)" << endl;
}
~ListNode_CPP()
{
cout << "~ListNode_CPP()" << endl;
}
};
int main()
{
ListNode_CPP* node4 = new ListNode_CPP;
ListNode_CPP* node5 = new ListNode_CPP(5);
delete node4;
delete node5;
return 0;
}
void f(int n)
{
//Sum* p = new Sum[10];
}
int main()
{
ListNode_CPP a[10];//调有10次拷贝构造
ListNode_CPP* p = new ListNode_CPP[10];
delete[] p;
return 0;
}
2.operator new和malloc的区别:他们使用方式都一样,处理错误的方式不一样,operator new 失败抛异常。
class A
{
public:
A()
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
int main()
{
A* p1 = (A*)malloc(sizeof(A));
A* p2 = new A;
A* p3 = (A*)operator new(sizeof(A));
//operator new和malloc的区别
//他们使用方式都一样,处理错误的方式不一样
size_t size = 1;
void* p4 = malloc(size*1024*1024*1024*2);
cout << p4 << endl;//失败返回0
free(p4);
try
{
void* p5 = malloc(size * 1024 * 1024 * 1024 * 2);
cout << p5 << endl;//失败抛异常(面向对象处理错误的方式)
//operator delete(p5);
}
catch (exception& e)
{
cout << e.what() << endl;
}
return 0;
}
3.malloc,operator new,new,free,operator free,delete 的区别。
malloc
operator new//==>malloc+失败抛异常实现
new //==>operator+构造函数
new比起malloc不一样的地方:1.调用构造函数初始化 2.失败了抛异常
delete比起free不一样的地方:1.调用析构函数清理operator free和free没区别,因为释放空间失败直接终止进程,是因为要跟operator new成对出现
4.内存池:
struct ListNode
{
ListNode* _next;
ListNode* _prev;
int _data;
void* operator new(size_t n)
{
void* p = nullptr;
p = allocator<ListNode>().allocate(1);//内存池
cout << "memory pool allocate" << endl;
return p;
}
void operator delete(void* p)
{
allocator<ListNode>().deallocate((ListNode*)p,1);//内存池
cout << "memory pool deallocate" << endl;
}
};
class List
{
public:
List()
{
_head = new ListNode;//全局operator new+构造函数
_head->next = _head;
_head->prev = _head;
}
~List()
{
ListNode* cur = _head->next;
while (cur != _head)
{
ListNode* next = cur->_next;
delete cur;
cur = next;
}
delete _head;
_head = nullptr;
}
private:
struct ListNode* _head;
};
int main()
{
List l;
return 0;
}
5.对已经存在的一块空间调用构造函数初始化。定位new/replacement new。new(对象)(空间的指针类型)(参数)。
class A
{
public:
A(int a=0)
:_a(a)
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
int main()
{
A* p1 = new A;
delete p1;
//想模拟上面的行为
//显示调用了A的构造函数和析构函数
A* p2 =(A*) operator new(sizeof(A));
//对已经存在的一块空间调用构造函数初始化。定位new/replacement new
new(p2)A(10);//new(对象)(空间的指针类型)(参数)
p2->~A();
operator delete(p2);
return 0;
}
6.内存泄漏:
int main() { //1G char* p = new char[1024 * 1024 * 1024]; //内存泄漏:p指向的空间不需要了,忘记或其他原因没有释放p指向的空间,就内存泄漏 //内存泄漏危害:长期运行的程序(游戏服务),出现内存泄漏危害很大,或者设备的内存本身很小也有危害 return 0; }
7.泛型编程,模板->写跟类型无关的代码,函数模板
函数重载有时太过于繁琐:如:
void Swap(int& left, int& right)
{
int tmp = left;
left = right;
right = tmp;
}
void Swap(double& left, double& right)
{
double tmp = left;
left = right;
right = tmp;
}
void Swap(char& left, char& right)
{
char tmp = left;
left = right;
right = tmp;
}
int main()
{
int a = 0, b = 1;
Swap(a, b);
double c = 1.1, d = 2.2;
Swap(c, d);
return 0;
}
所以可以用函数模板:
//泛型编程
//模板->写跟类型无关的代码
//函数模板
template<class T>
template<typename T>//模板参数-》类型
void Swap(T& x1, T& x2)
{
T x = x1;
x1 = x2;
x2 = x;
}
//下面调用的是否是同一个函数?
//不是
//这里我们不能调用模板,调用的是函数模板实例化生成的对应类型的函数
int main()
{
int a = 0, b = 1;
Swap(a, b);
double c = 1.1, d = 2.2;
Swap(c, d);
char e = 'a', f = 'b';
Swap(e, f);
return 0;
}
8.C语言的一些问题,C++可以通过构造,析构,模板解决:
//C语言如何实现一个栈
typedef int STDateType;
struct Stack
{
int* _a;
int size;
int _capacity;
};
typedef struct Stack Stack;
void StackInit(Stack* ps)
{}
void StackDeatory(Stack* ps)
{}
void StackPush(Stack* ps,STDateType x)
{}
void StackPop(Stack* ps)
{}
template<class T>
class Stack_CPP
{
public:
Stack_CPP()
{
}
~Stack_CPP()
{
}
void Push(T x)
{}
private:
T* _a;
int _size;
int _capacity;
};
int main()
{ //C语言的问题 C++如何解决
//1.忘记初始化和销毁 ->构造函数+析构函数
//2.没有封装,谁都可以修改结构体的数据 ->类+访问限定符
//3.如果想同时定义两个栈,一个栈存int,一个栈存double,做不到 ->模板
Stack st;
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
//非法修改
st._capacity = 0;
StackDeatory(&st);
Stack_CPP<int> st_cpp_int;
st_cpp_int.Push(1);//实际上我也有两个参数,有一个是隐含的this指针
st_cpp_int.Push(2);
st_cpp_int.Push(3);
st_cpp_int.Push(4);
Stack_CPP<double> st_cpp_double;
st_cpp_double.Push(1.1);
st_cpp_double.Push(2.2);
return 0;
}