c/c++内存管理和模板

发布时间:2026/6/1 16:27:31

c/c++内存管理和模板 一C/C内存管理一c语言动态内存管理C 语言的动态内存管理是对堆内存的手动分配使用与释放过程堆内存提供了灵活的大小控制但需要开发者完全负责其生命周期管理。所有动态内存函数都定义在stdlib.h头文件中返回值均为void*类型需要强制转换为具体类型使用。1malloc申请未初始化的内存void* malloc(size_t size);向堆区申请size字节的连续内存空间size是需要申请的内存字节数申请成功返回指向申请内存起始地址的void*指针需要强制转换为具体类型使用申请失败返回NULL。申请的内存不会被初始化内容是随机值。2calloc申请并初始化内存void* calloc(size_t size, size_t size);向堆区申请num个大小为size字节的连续内存空间num是元素个数size是每个元素的字节数返回值同malloc申请的内存会被自动初始化为 0这是与malloc的主要区别。3realloc调整已申请内存的大小void* realloc(void* ptr, size_t newSize);调整ptr指向的动态内存的大小为newSize字节ptr是之前动态开辟的空间指针newSize是调整后的新大小字节。申请成功返回指向调整后内存的指针申请分为两种情况原地扩容和异地扩容原地扩容是原内存后面有足够的连续空间直接在原内存基础上扩展返回原指针异地扩容是原内存后面没有足够空间重新申请一块新的更大内存将原数据复制过去释放原内存返回新指针找到新空间拷贝旧数据释放旧空间。申请失败则返回NULL原内存保持不变。如果ptr为NULL则realloc等价于mallocnewSize。二c的动态内存管理1内置数据类型的动态分配int* ptr1 (int*)malloc(5 * sizeof(int));//不能初始化 int* ptr2 new int[5] {5, 4, 3, 2, 1}; //可以初始化 free(ptr1); ptr1 nullptr; delete[] ptr2; ptr2 nullptr;分配数组用new 类型[大小]释放必须用delete[]。若用delete释放数组只会调用第一个元素的析构函数导致内存泄漏。new[]会额外存储数组的大小信息delete[]会根据这个信息调用所有元素的析构函数。如果申请空间失败就会抛出异常就不用自己去判断分配空间是否成功了。2自定义类型的动态分配class A{ public: A(int a) :_a(a){ cout A(int a) endl; } ~A(){ cout ~A() endl; } private: int _a; }; int main(){ A* p1 (A*)malloc(5 * sizeof(A)); free(p1); p1 NULL; A* p2 new A[5]{ 1,2,3,4,5 }; delete[] p2; return 0; }在申请自定义类型的空间时new会调用构造函数delete会调用析构函数在以上代码中new 会调用五次构造函数并初始化delete会调用五次析构函数。而malloc和free不会调用。二template(模板)一函数模板1单个模板参数函数模板是 C泛型编程的核心工具允许你编写与类型无关的通用代码编译器会根据调用时的实际类型自动生成对应的函数版本极大地减少了代码重复同时保持了类型安全。函数模板完美解决了这些问题一份代码适配所有类型且编译期进行类型检查。templatetypename T void Swap(T x1, T x2){ T tmp x1; x1 x2; x2 tmp; } int main(){ int i 3; int j 7; cout 交换前 i j endl;//3 7 Swap(i, j); cout 交换后 i j endl;//7 3 double d1 3.5; double d2 1.89; cout 交换前 d1 d2 endl;//3.5 1.89 Swap(d1, d2); cout 交换后 d1 d2 endl;//1.89 3.5 return 0; }这样我们就不用再写多个交换函数了。2多个模板参数调用时参数可以是多种类型。templateclass T1,class T2,class T3 double Arithmetic(const T1 x1,const T2 x2,const T3 x3){ return x1 x2 x3; } int main() { cout Arithmetic(1, 3.4, 1.256) endl; cout Arithmetic(1, 3, 5) endl; cout Arithmetic(2.19, 3.4, 1.256) endl; return 0; }二类模板以下是实现了一个栈的类模板#includeiostream #includeassert.h using namespace std; namespace zS{ templateclass SDatatype class stack{ public: stack(int n 4) :_arr(new SDatatype[n]) , _size(0) , _capacity(n) { } void ExpandCapacity(); void Push(SDatatype x); SDatatype stacktop()const; void stackPop(); bool Empty()const; int stackSize()const; ~stack(){ delete[] _arr; this-_size _capacity 0; } private: SDatatype* _arr; int _size; int _capacity; }; } templateclass SDatatype void zS::stackSDatatype::ExpandCapacity(){ SDatatype* NewCapa new SDatatype[this-_capacity * 2]; memcpy(NewCapa, this-_arr, this-_capacity * sizeof(SDatatype)); delete[] _arr; _arr NewCapa; this-_capacity * 2; } templateclass SDatatype void zS::stackSDatatype::Push(SDatatype x){ if (this-_size _capacity) { ExpandCapacity(); } this-_arr[_size] x; } templateclass SDatatype bool zS::stackSDatatype::Empty()const{ return _size 0; } templateclass SDatatype SDatatype zS::stackSDatatype::stacktop()const{ assert(!Empty()); return _arr[_size - 1]; } templateclass SDatatype void zS::stackSDatatype::stackPop(){ assert(!Empty()); --this-_size; } templateclass SDatatype int zS::stackSDatatype::stackSize()const{ return this-_size; }

相关新闻