当前位置: 首页 > article >正文

从入门到了解C++系列-----内存管理 + 初步了解模板

目录

 

前言

  1.c/c++ 的内存分布

2. c++ 中内存管理方式

  2.1 有什么

  2.2 怎么用

     2.2.1 new

    2.2.2 delete

    2.2.3 operator new 与 operator delete

2.3 内存泄露

    2.3.1 是什么

    2.3.2 检测内存泄漏

 3. 模板

   3.1 是什么

   3.2 怎么用

   3.3 深入了解模板

   3.4 类模板

3.4.1 深入分析类模板

 结尾:


前言

    本篇文章是对于 c++中内存管理的讲解。将会讲解两个部分:一个是数据的存储,另外一个是new 与 delete。也是对于我学习内容的总结与分析。

  1.c/c++ 的内存分布

   请看下面一段代码,分析其中的代码数据分别是存放在什么区域。 

int gloabval = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = { 1, 2, 3, 4 };
char char2[] = "abcd";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
free(ptr1);
free(ptr3);
}

首先1.globalvar 是一个全局变量,存放在 c 静态区里面。第二个为 c, staticVar是静态变量存放在栈上 C,local 是局部变量存放在栈,num1 数组名存放在栈上 A。char2 数组名存放在栈上 A。*char 相当于是对首元素的地址进行解引用,但是数组内容还是存放在栈上。pchar3 指针变量名存放在栈上,为 A。*pchar3 是 a 存放在代码段上 D。ptr1是 int 型指针的名字,所以是存放在栈,但是 *ptr1是malloc 开辟的空间,存放在堆上 B。

    答案为:C C C A A A A A D A B (从左向右,从上到下)

    下面一道题是计算所占空间的大小。

     sizeof 于 strlen 的区别在于 sizeof 是取到 '\0' 为止,而strlen是就是字符串的长度,其次sizeof是运算符,而strlen是函数。指针的所占字节就是 4 、8个。

2. c++ 中内存管理方式

  2.1 有什么

    在c++中重新定义了 new 于 delete,来进行实现动态内存的开辟。

  2.2 怎么用

     2.2.1 new

int* a = new int;//注意返回值的类型为指针类型
int* b = new int[10];//这是开辟10个空间
int* c = new int(10);//这是开辟了一个空间,将里面的内容初始化为了 10
int* d = (int*)malloc(sizeof(int));

    new的基本使用如上,它的这种使用方法与 malloc 没有区别。但是对于自定义类型(类)就有很大的区别。

new可以自动调用构造于析构函数,但是 malloc 不可以。 

class Stack
{
public:
    Stack()
   {
      _a = 0;
     cout<< "Stack()" << endl; 
   }

private:
   int _a;
   int _b;
}
int main()
{
   Stack* a = new Stack;
   Stack* b = (Stack*)malloc(sizeof(Stack));
}

    2.2.2 delete

    delete就是释放,动态内存开辟的空间(以上面的代码为例)

//释放开辟好的一个空间
delete a;
//释放开辟好的好几个空间
delete[] b;

     同样的道理,delete与free最大的区别在于,在delets在清除的时候会调用析构函数(不只是类,跟准确来说是自定义类型)。而free不可以,我就不写代码了。

   2.2.3 operator new 与 operator delete

    new 与 delete 是操作符,而 operator new 与 operator delete 是系统提供的全局函数,new 与 delete 的底层也是调用的这两个函数。

    然而 operator  new / delete,在实现的时候使用的是 malloc 与 free。而最大的区别在于 operator new/delete 在失败的时候会抛异常。他的代码实现如下,对于我现在的水平来说实现有点复杂。

   2.2.4 总结

    1.new = operator new + 构造函数。  delete  = operator delete + 析构函数。

    2. operator new = malloc + 抛异常。 operator = free + 抛异常。

常见的面试题目:区分malloc 与 new 的相同点与不同点(free 与 delete 类似):

相同点:都是在堆上进行空间的开辟与释放。并且需要进行手动的释放。 、

不同点:1. 就是 new 比 malloc 多了一个构造函数(针对于自定义类型) + 没有生成成功的话会抛异常。

               2. new 是操作符,而 malloc 与 free是函数。

               3. malloc 在生成空间时需要手动输入所占的字节大小,而 new 只需要加上需要开辟的空间的类型即可,如果是想要开辟多个空间的话[n],直接这样写就可以。

                4. malloc 返回的时 void* 类型的地址,需要进行强制转化,但是 new 不需要。

2.3 内存泄露

    2.3.1 是什么

    内存的泄露是指由于 malloc 与 new 开辟可空间但是没有进行释放,导致内存空间的浪费。开辟空间是在堆上开辟的空间,由于堆的内存空间大小是非常有限的,与代码区、硬盘不是一个级别,会很容易造成浪费。

    2.3.2 检测内存泄漏

    这一部分的内容不进行详细的解释,了解即可。在这里我推荐给大家几个进行检测内存泄漏的工具。
1.在linux下内存泄漏检测:Linux下几款C++程序中的内存泄露检查工具_c++内存泄露工具分析-CSDN博客
2.在windows下使用第三方工具:VS编程内存泄漏:VLD(Visual LeakDetector)内存泄露库_visual leak detector vs2020-CSDN博客
3.其他工具:内存泄露检测工具比较 - 默默淡然 - 博客园

 3. 模板

   3.1 是什么

    简单来说,模板就相当于是一个懒人工具,使用模板时会自动来调用对应的类型,自动实现相应转化。需要注意的是如果我们不调用模板函数的话,就不会编译相应的内容,也就是说不用的情况下,有错误也不会报错。有时也称之为范式编程。

    3.2 怎么用

template<class T> //也可以将里面的内容替换为: typename T
T add(T &a,T &b)// 如果是返回值的话是需要返回的类型为 T
{
    return a + b;
}
int main()
{
    int a = 1, b = 2;
    int c = add(a, b);
    cout<< c << endl;
    double a1 = 1.1, b1 = 2.2;
    double c1 = add(a1, b1);
    cout<< c1 << endl;
}

 代码的使用如上所示。

  3.3 深入了解模板

    那模板是为了解决什么问题呢?c ++ 跟 c 的不同又是在哪里,c++做了一些什么?让我带着这些问题来进行下面的解释。

    如果我们想要同时实现不同数据类型的 Stack,以及不希望里面的内容进行改变、同时还希望不用自己手动去调用析构函数自动实现内存的释放,为了解决这些问题,C++ 里面的类 + 模板就很好的解决了这样的问题。

 3.4 类模板

    前面介绍的是函数模板实现不同类型的函数,此小节是模板函数的另外一个分类为:类的模板

以栈为例子进行分析。代码如下:

template<class T>
class Vector
{
public:
    //栈的初始化
    Vector(size_t capacity = 0)
        :a(new T[capacity])
        , size_t capacity(capacity)
        , size_t size(0)
    {
    }
    //栈析构函数
    ~Vector()
    { }
    //尾插
    void Push_Back(const T& x);
    //尾删
    void Pop_Back();
    //返回长度大小, 类内定义,类内实现
    size_t Size()
    {
        return _size;
    }

    //[] 函数的重载,找到 pos 位置所对应的代码
    T& operator[](size_t pos)
    {
        assert(pos >= size && pos <= capacity);
        return a[pos];
    }

private:
    T* a;
    size_t capacity;
    size_t size;
};
// 类内定义,类外实现
template<class T>
void Vector<T>::Push_Back(const T& x);

template<class T>
Vector<T>::~Vector()
{
    if (a)
    {
        delete[] a;
    }
    capacity = size = 0;
}
int mian()
{
    Vector<int> s;//定义 int 类型的s
    Vector<double> s1;//定义 double 类型的 s1;
}

3.4.1 深入分析类模板

     

不要小看内存泄漏问题,我们创建一个栈,开辟完一个空间之后很容易忘记进行销毁空间。类两个函数就很好的解决了这种问题。 同时也解决了外部不可以修改内容的问题

 4. 结尾:

 如果对你有帮助还请帮我点个免费的赞,支持一下我,我也会不断地改进争取写出跟高质量的文章。我们共同努力!!!!😊😊😊


http://www.kler.cn/a/392860.html

相关文章:

  • 前端框架大比拼:React.js, Vue.js 及 Angular 的优势与适用场景探讨
  • 基于标签相关性的多标签学习
  • 前端--> nginx-->gateway产生的跨域问题分析
  • const限定符-C语言中指针的“可变与不可变”法则
  • MySQL数据库:SQL语言入门 【上】(学习笔记)
  • 科技云报到:数字化转型,从不确定性到确定性的关键路径
  • CSS Modules是什么?
  • 【软件开发】Spring 面向切面编程(头歌作业)
  • 小程序租赁系统打造便捷租赁体验助力共享经济发展
  • HO-PEG-MACA中PEG的修饰使其提高了稳定性,有助于其在各种溶剂中保持稳定的性能。
  • 冗余连接2 hard题 代随C#写法
  • 【数据结构】10.线索二叉树
  • 【Verilog】case、casex、casez的区别
  • MySQL中的事务与锁
  • opencv入门学习总结
  • 游戏服务器和普通服务器的区别
  • Shell编程之正则表达式与文本处理器
  • 游程编码 (Run-length Encoding)详细解读
  • 【go从零单排】Logging
  • uniapp中多角色导致tabbar过多的解决方式
  • 基于Python的自然语言处理系列(59):MultiRetrievalQAChain 实现
  • 基于SSM的“汽车销售分析与管理系统”的设计与实现(源码+数据库+文档+PPT)
  • 笔记本电脑定期保养
  • SwiftUI开发教程系列 - 第十二章:本地化与多语言支持
  • 贪心算法入门(二)
  • 【ROS的Navigation导航系统】