C/C++内存管理

C/C++内存管理

1. C/C++内存分布

C++兼容C,因此内存分布都是一样的:

栈区:局部变量;堆区:malloc、calloc、realloc出来的对象

在const char* p1 = "abcd"和char str[] = "abcd"中,p1和str以及*p1和 *str分别存放在什么地方?

p1和str都是局部变量,都是存放在栈区;p1指向的"abcd"是存放在代码段的,所以p1是指向的代码段,*p1就是’a’字符,是存放在代码段的,所以 *p1是存放在代码段的,但是str是数组,"abcd"必须拷贝一份放在栈区,所以 *str是存放在栈区的

2. C++中动态内存管理

为什么需要内存管理?

对内存进行分类,这样操作系统对内存会更好的进行管理

2.1 new与delete操作内置类型

2.2 new与delete操作自定义类型

总结

C++的new和delete内存管理和C语言的mallloc和free最大的区别是:对于自定义类型来说,除了开空间外,C++的内存管理方式还调用了构造函数和析构函数。

3. operator new 和 operator delete函数

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

Visual studio 2019中operator new底层实现

void* __CRTDECL operator new(size_t const size)
{
        for (;;)
        {
            if (void* const block = malloc(size))
            {
                return block;
            }

            if (_callnewh(size) == 0)
            {
                if (size == SIZE_MAX)
                {
                    __scrt_throw_std_bad_array_new_length();
                }
                else
                {
                    __scrt_throw_std_bad_alloc(); //抛出异常
                }
            }
            // The new handler was successful; try to allocate again...
        }
}

Visual studio 2019中operator delete底层实现

void __CRTDECL operator delete(void* const block, size_t const) noexcept
{
		operator delete(block);
}

void __CRTDECL operator delete(void* const block) noexcept
{
#ifdef _DEBUG
		_free_dbg(block, _UNKNOWN_BLOCK);
#else
		free(block);
#endif
}

Visual studio 2019中operator new[]底层实现

void* __CRTDECL operator new[](size_t const size)
{
    return operator new(size); //原理调用的size次operator new函数
}

Visual studio 2019中operator delete底层实现

void __CRTDECL operator delete[](void* const block) noexcept
{
	operator delete(block);
}
void __CRTDECL operator delete[](void* const block, size_t const) noexcept
{
	operator delete[](block);
}

总结

  1. new和delete的本质:malloc和free的封装

  2. new和malloc的机制:new失败了抛异常,malloc失败了返回NULL

  3. 对于内置类型,new和malloc以及delete和free类似,不同的地方在于new失败了抛异常,malloc失败了返回NULL

  4. 对于自定义类型,new的原理:1.调用operator new函数申请空间 2.调用构造函数

  5. 对于自定义类型,delete的原理:1.调用析构函数 2.调用operator delete函数释放空间

  6. 对于自定义类型,new object[Number] 的原理:1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请 2. 在申请的空间上执行N次构造函数

  7. 对于自定义类型吗,delete[]的原理:1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理 2.调用operator delete[]释放空间,实际在operator delete[]中调用N次operator delete来释放空间

  8. new和delete必须匹配使用,不要new和free以及malloc和delete交叉使用

4. 定位new表达式

4.1 背景

class A
{
public:
	A(int a) 
		:_a(a)
	{
		cout << "A()" << endl;
	}
	~A() {
		cout << "~A()" << endl;
	}

private:
	int _a;
};
int main()
{
	A* p = (A*)malloc(sizeof(A));
	if (p == nullptr) {
		perror("malloc is failed");
		exit(-1);
	}
	//想对已经定义好的对象初始化怎么做?
	return 0;
}

解决方案:

class A
{
public:
	A(int a) 
		:_a(a)
	{
		cout << "A()" << endl;
	}
	~A() {
		cout << "~A()" << endl;
	}

private:
	int _a;
};
int main()
{
	A* p = (A*)malloc(sizeof(A));
	if (p == nullptr) {
		perror("malloc is failed");
		exit(-1);
	}
	new(p)A(1); //定位new

	return 0;
}

4.2 基本语法

定位new表达式是:在已分配的原始内存空间中调用构造函数初始化一个对象

使用格式:new(指针)type或者new(指针)type(初始化列表)

使用场景:一般配合内存池使。因为内存池分配出的内存没有初始化,所以如果定义自定义类型对象,需要使用new的定义表达式进行显示调用构造函数进行初始化

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脚踏车(crush)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值