C++ 动态内存 new/delete用法
Posted Jqivin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 动态内存 new/delete用法相关的知识,希望对你有一定的参考价值。
一、动态内存是什么?
动态内存是在堆区空间的内存。是指在程序运行过程中动态分配的内存。这些内存如果程序员不自己释放,操作系统不会帮你释放。通过new申请,delete释放。
栈内存
:保存定义在函数内部的的非静态对象(或变量),函数作用域结束函数栈帧销毁,这个函数所使用的栈内存就被释放,由操作系统管理。
静态内存
:使用之前分配,程序结束销毁。
二、何时使用动态内存
1.程序不知道自己使用多少对象
2.程序不知道所需对象的准确类型
3.程序需要在多个对象间共享数据
就比如容器类。
一个小例子
using namespace std;
class Object
{private:int a;
public:
Object(int n = 0) :a(n) { cout << "construct" << endl; }
~Object() { cout << "destory" << endl; }
int get() { return a;}
};
Object* fun1()
{
Object o1(10);
Object* p1 = &o1;
return p1;
}
Object* fun2()
{
Object* p2 = new Object(20);
return p2;
}
int main()
{
Object* p1 = fun1();
cout << p1->get() << endl;
Object* p2 = fun2();
cout << p2->get() << endl;
delete p2;
return 0;
}
输出结果:栈区资源函数结束就被释放掉了,堆区空间并没有被释放掉。
三、new/delete的使用
1.new开辟动态内存
new有三种用法
(1)关键字new :申请空间,构建对象
(2)::operator new:只是申请空间,不构建对象
(3)定位new:在一块已经分配成功的内存上重新构造对象
一般(2)(3)一块使用
#include<iostream>
#include<memory>
using namespace std;
#if 1
class Object
{
private:
int value;
public:
Object(int val = 0) :value(val) { cout << "construct Object" << endl; }
~Object() { cout << "destruct Object" << endl; }
int Value() { return value; }
const int Value() const { return value; }
};
int main()
{
//new的用法 (1)关键字
int* i = new int(10);
Object* obj = new Object(10); delete obj;
int* is = new int[] {1, 2, 3}; //new []
delete is;
unique_ptr<int[]> ps1(new int[10]{ 1,2,3,4,5,6,7,8,9,10 }); //和智能指针一块使用
Object* Obj = new Object[]{ 10,20,30 }; //只能用Object*接收,可以使用[]
cout << Obj[1].Value() << endl;
delete []Obj;
unique_ptr<Object[] > pobj(new Object[]{ 10,20,30 });
//(2)operator new --- 类似malloc
int* io = (int*)::operator new(sizeof(int)); cout << *io << endl;//还未赋值,所以是随机值
int* ios = (int*)::operator new(sizeof(int)*3);
Object* objo = (Object*)::operator new(sizeof(Object));
//Object* obja = (Object*)::operator new(sizeof(Object) * 3); //数组空间
void* obja = operator new(sizeof(Object) * 3);
//(3)定位new
new(io) int(100);
new(ios) int[3]{ 1,2,3 };
objo = new(objo) Object(1);
Object* objas = new(obja) Object[3]{ 11,22,33 };
for (int i = 0; i < 3; i++)
{
cout << ios[i] << " " << objas[i].Value() << endl;
}
delete io; delete ios; //不用[]
delete objo;
//delete [] 不可以使用
for (int i = 0; i < 3; i++)
{
objas[i].~Object();
}
delete objas;
return 0;
}
#endif
结果
2. delete释放内存
delete有两个动作:
(1)调用对象的析构,销毁对象
(2)释放对象占用的堆区空间。
delete 指针变量名; //必须是指针变量名,不能是对象。
delete [] 释放数组对象。
四、关于new的用法区别
new [] 创建数组对象的时候,会在头部信息中保存数组中有几个元素,所以可以使用
delete[],
operator new相当于malloc,数据区域上方保存的是越界标志,如果这个时候
使用delete[] 会把越界标志当做元素个数,所以会出现调用0xfdfdfdfd次析构函数。
代码
class Object
{
private:
int value;
public:
Object(int val = 0) :value(val) { cout << "construct Object" << endl; }
~Object() { cout << "destruct Object" << endl; }
int Value() { return value; }
const int Value() const { return value; }
};
int main()
{
Object* p = (Object*)::operator new(sizeof(Object) * 3);
new(p) Object[3]{ Object(10),Object(20),Object(30) };
Object* p1 = new Object[3]{ Object(10),Object(20),Object(30) };
for (int i = 0; i < 3; i++)
{
cout << p[i].Value() << endl;
}
for (int i = 0; i < 3; i++)
{
cout << p1[i].Value() << endl;
}
delete[] p1;
delete []p;
}
结果
会调用0xfdfdfdfd次析构函数。
正确的写法
:
delete[] p1;
for (int i = 0; i < 3; i++)
{
p[i].~Object();
}
delete p;
原因: new[] 会记录数组中元素的个数,delete[]的时候会知道调用几次析构函数,但是operator new相当于malloc只有上越界标志,没有元素个数,所以执行delete[]的时候会错把上越界标志当成元素个数,从而一直执行析构函数。
总结:
operator new + 定位new构造数组对象时,不要使用delete[].
以上是关于C++ 动态内存 new/delete用法的主要内容,如果未能解决你的问题,请参考以下文章