news 2026/6/10 22:29:21

模板跟string的实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
模板跟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是否成功(失败返回NULL,p2仍然有效) 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的,因为这样不用进行类型转换
  • 类模板必须实例化,要不不会推导
  • 误区 1:operator new分配的内存永远在堆上,绝不会开到栈上

    operator new本质就是堆内存申请接口,new Stack<double>第一步分配出来的Stack对象本体,是堆内存,不是栈;只有普通局部变量Stack<double> st;的对象本体才在栈上。

    误区 2:不是 “构造成员变量时开空间”,是构造函数执行时,手动给指针成员再申请一块独立堆内存

    完整分步拆解

    cpp

    运行

    Stack<double>* pst = new Stack<double>;

    第 1 步:operator new(堆)

    向操作系统申请一块堆内存,大小刚好容纳Stack<double>的所有成员变量:_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(第一层)】 Stack<double> 对象 ├─ _array 指针 → 保存地址B ├─ _size └─ _capacity 【堆内存 地址B(第二层)】 连续double元素数组(真正存数据)
  • 前面两个只是调用构造跟析构函数建立临时对象在栈上,pst也在栈上,它指向的空间在堆上
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 22:10:00

从矩阵乘法到图像处理:实战演示Verilog二维数组在FPGA算法中的高级用法

从矩阵乘法到图像处理&#xff1a;实战演示Verilog二维数组在FPGA算法中的高级用法 在FPGA开发中&#xff0c;Verilog二维数组是实现复杂算法的关键数据结构。与软件编程不同&#xff0c;硬件描述语言中的数组操作需要考虑并行性、时序约束和资源消耗等独特因素。本文将深入探讨…

作者头像 李华