C++内存管理(1)

C++ 内存管理

C++内存分配

	一般来说C++ 操作内存用的是 new/ delete 
	实际最后最用调用的是malloc /free 
	调用层次如下
	![转自侯捷老师ppt](https://img-blog.csdnimg.cn/17390fe79cb24acb8878e1c78db5b1ca.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjE5MzcwNA==,size_16,color_FFFFFF,t_70)

最后malloc 和free 就会调用来自操作系统的API 来实现真正的分配内存,当然我们也可以直接调用操作系统的api来分配内存使用,只是一般情况下我们不会这么操作。

C++ 使用new 分配的时候做了什么

new 实际上应该被称为 operator new( ) 除此之外还有一个::operator new() 表示全局的new 当然与之对弈的 也有operator delete, ::operator delete 这两个函数也是允许被重载的,本文说的的内存管理基本上是基于对几个函数的操作。
回到主题 我们在使用new 的时候编译器会帮我们做哪些额外的操作呢?
class A
{
public :
        A()
        {

        }

} ;
int main(void)
{
        A * a = new A();
        delete a;
        return 0;
}

比如这个代码
编译器在看到new 只会就会将代码扩充成这个样子

class A
{
public :
        A()
        {

        }

} ;
int main(void)
{
        // A * a = new A();
		//上面这句就会被扩展成这个样子
        A * a;
        try{
                void *mem = operator new (sizoef(A) );
                a = static_cast<A *>(mem);
                a->A::A();
          		//直接调用构造函数是不被允许的,只有编译器扩展的才可以调用      
        }
        catch(std::bad_alloc)
        {
        }
        //new end
        //delete a;
        //delete 扩展
        a->~A();//可以手动调用
        operator delete(a)//delete end 
        
        return 0;
}

这样我们就可以很清晰的知道 如果重载了 new /delete 是在什么时候被调用的 同时我们也知道了 程序员是不能手动调用构造函数的,如果要调用要怎么操作呢,C++提供了一种原地创建对象的方式(在指定地址创建对象)new §A(); 在p 所指向的位置创建这个对象,这个在后面也有详细的说明。
了解了这个我们在了解一下 new 一个数组的时候是怎么操作的 以及为什么new 数组为什么要使用delete[]

分配一个数组

#include <iostream>
using namespace  std;
class A
{
public :
        A()
        {

        }

} ;
int main(void)
{
        A *a = new A[3];
        delete [] a ;
        return 0;
}

上面代码创建 了一个大小为3 的数组 然后调用delete 释放了这个空间
这里其实有一个一直没有解释的问题, 为什么创建的时候指定了个数,但是释放的时候没有指定要释放的个数呢?这里就涉及到了C++ 分配一个数组进行的一个操作。
在这里插入图片描述

a 指向的实际上是cookice 的位置 在delete 的时候因为Cookice 中有记录这样就可以成功的调用这里所有的析构函数,如果没有 调用delete [] 调用的是 delete 会发生什么呢,很显然就会没有调用下面对象的析构函数 这样会内存泄露吗 实际上这里new 的空间是放回去了, 但是如果 数组中析构函数有delete 就不会被调用到 所以还是存在内存泄露的风险。

cookice 的位置有可能在上面有可能在下面这取决于平台实现 对于程序员来说其实并不需要关心

#include <iostream>
using namespace  std;
class A
{
public :
        A()
        {
        }
        A(int _id )
        :id(_id)
        {
                cout<<"this "<<this<<"  id = "<<id<<endl;
        }
        ~A()
        {
                cout<<"~ this "<<this<<"  id = "<<id<<endl;
        }
private :
        int id;
} ;
int main(void)
{
        A *a = new A[3];
        A * temp = a;
        for(int i = 0;i<3;i++)
        {
                new(temp ++ )A(i);
                // 这里我们就是用上面说的在指定空间中创建对象
        }
        delete [] a ;
        return 0;
}

使用这个我们可以测试释放方式
在这里插入图片描述
就此我们就知道了C++ 在new 实际上干了什么 ,实际上operator new /delete 内部还是调用malloc()接下来我们就要尝试 重载new、delete来实现一些操作

重载operator new / operator delete

根据上面的说法 每次在使用new 的时候都会展开使用operator new C++ 是允许这个的重载
通过上面的展开代码我们也知道了重载以后具体调用在哪里

简单的分配器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值