模板跟string的实现

📅 2026/6/18 21:36:12 👤 管理员 👁 次浏览
模板跟string的实现
全局变量和静态变量无论全局还是函数内生命周期贯穿整个程序运行期都存放在数据段静态区。区别仅在于作用域static限制了作用域不影响内存分区。localVar/num1/char2函数内的局部变量、局部数组都在栈上分配内存函数返回时栈帧自动销毁。char2[] abcd是把字符串常量abcd拷贝到栈上的数组里数组本身在栈上。pChar3变量本身指针变量pChar3是局部变量存放在栈上。*pChar3指向的内容pChar3指向的abcd是字符串常量存放在代码段常量区只读不可修改。ptr1变量本身指针变量ptr1是局部变量存放在栈上。注意ptr1指向的malloc分配的内存存放在堆上但题目问的是ptr1这个变量本身的位置所以是栈。两层堆内存位置总结int* p2 (int*)calloc(4, sizeof(int)); // 先检查分配是否成功 if (p2 NULL) { /* 错误处理 */ } // 扩容 int* p3 (int*)realloc(p2, sizeof(int)*10); // 必须检查realloc是否成功失败返回NULLp2仍然有效 if (p3 NULL) { free(p2); // 失败时要释放原内存避免泄漏 return; } // 成功后p3接管内存只需要free(p3) free(p3);有名对象会调用拷贝构造匿名对象直接省略拷贝构造这个是隐式类型转换也不拷贝构造先重载开空间再用构造来赋值delete先析构再operator delete小括号是初始化的值是构造时用的中括号是个数。定位new在内存池中使用的比较多。new A(1)调用 operator new 分配内存调用 A::A(1) 构造对象。delete p1调用 A::~A() 析构对象调用 operator delete 释放内存。第二行没有构造函数不能进行析构上下两种实现的效果是一样的普通 new分配 构造 绑定死内存池 定位 new分配 和 构造 彻底分开先拿内存 → 不初始化要用时 → 定位 new 构造不用时 → 只析构不释放内存还给池 → 重复利用调用的函数不是同一个、T只能识别一种类型不能同时传多种类型类型不同可以使用强制类型转换但会导致结果不同。显式实例化多了一个隐式类型转换T不做对应的形参不知道传的实参是啥类型就必须用显式实例化会调用不含t的因为这样不用进行类型转换类模板必须实例化要不不会推导误区 1operator new分配的内存永远在堆上绝不会开到栈上operator new本质就是堆内存申请接口new Stackdouble第一步分配出来的Stack对象本体是堆内存不是栈只有普通局部变量Stackdouble st;的对象本体才在栈上。误区 2不是 “构造成员变量时开空间”是构造函数执行时手动给指针成员再申请一块独立堆内存完整分步拆解cpp运行Stackdouble* pst new Stackdouble;第 1 步operator new堆向操作系统申请一块堆内存大小刚好容纳Stackdouble的所有成员变量_array指针、_size、_capacity。此时这块堆内存里只是一片原始二进制空间成员指针_array是随机野指针没有指向有效内存成员变量只是内存占位没初始化。第 2 步调用类构造函数对象初始化进入构造函数函数体执行手写的初始化代码给_size、_capacity赋值初始数值执行_array new double[初始容量];第二次调用堆申请开辟第二块独立堆内存用来存放栈实际存储的元素把新数组首地址赋值给成员指针_array。外层堆new出来的Stack对象本体存_array、_size、_capacity由pst指针指向内层堆_array指针再new[]出来的元素数组用来存真实double数据pst这个指针变量本身存于栈内存它只是记录外层堆对象的地址你自定义的析构里写了delete[] _array;先释放_array指向的内层元素数组堆内存。第 4 步operator delete内层内存释放完毕后释放pst指向的外层Stack对象本体堆内存两块堆内存全部回收不存储对象内容。【栈内存】 pst 指针变量 → 保存地址A 【堆内存 地址A第一层】 Stackdouble 对象 ├─ _array 指针 → 保存地址B ├─ _size └─ _capacity 【堆内存 地址B第二层】 连续double元素数组真正存数据前面两个只是调用构造跟析构函数建立临时对象在栈上pst也在栈上它指向的空间在堆上