栈内存与堆内存
声明的变量以及函数名是使用的栈内存,但是在动态内存管理中使用的是堆内存。 栈内存比较紧凑,所以有较大的局部相关性。 堆内存在运行期动态扩展,需要显示释放。new在运行期被调用 。 vector和string就是动态内存
== 一个例子来看new的用处 ==
- code_one
#include<iostream>
using namespace std;
int* fun()
{
int* res = new int(2);
return res;
}
int main()
{
int* y = fun();
cout << *y << endl;
return 0;
}
- code_two
#include<iostream>
using namespace std;
int* fun()
{
int res = 2;
return &res;
}
int main()
{
int* y = fun();
cout << *y << endl;
return 0;
}
两段代码都可以输出2;但是第二段代码很危险,因为new使用的是堆内存,需要手动释放,所以在未释放以前指针指向的内存以及内容都保留,所以可以成功输出2;但是第二段代码值存在栈内存中,在调用fun()函数以后,fun()函数中声明变量的内存就会自动释放,得到一个指针指向某地址,但是如果有其他内容存入同样的地址,那么输出的值就会使内存中存入的新值
- 对象的构造分为两步:分配内存与在所分配的内存上构造对象;销毁也分为两步
new的几种形式
1. 构造单一对象和单一数组
#include<iostream>
using namespace std;
int* fun()
{
int* res = new int(0);
*res = 2;
return res;
}
int main()
{
int A[5][5];
int* y = new int[5]{};
delete[] y;
cout << typeid(*A).name() << endl;
return 0;
}
2. nothrow new
new用来开辟内存,但是如果内存已经被分配完了,或者说留下的内存空间没有我们要求的连续的内存长度,就会出现开辟失败的情况,nothrow new就可以抛出异常
#include<iostream>
#include<new>
using namespace std;
int main()
{
int* y = new (nothrow) int[5]{};
if (y == nullptr)
{
}
cout << typeid(*A).name() << endl;
return 0;
}
3.placement new
例子:vector对像是动态内存处理的,可以在末尾加入新元素。但是如果遇到在添加元素的时候,后边没有与对象连续的内存空间供使用,vector首元素指向了8000,在8016处是另一个对象,那么就需要把当前对象的值复制到另外一块内存中,进而可以在后边添加元素。在复制元素到新内存空间以后,并没有创建对象,只有当新元素添加以后才会创建新的对象。一般情况两下复制到的新地址出空间连续长度为目前长度的两倍。
placement new意思就是已经有一块内存了,不需要分配测内存只需要在已知的内存上构建对象。
#include<iostream>
#include<new>
#include<vector>
using namespace std;
int main()
{
vector<int>* A = new vector<int>{1,2,3};
cout << (*A)[0] << endl;
int* y = new (A) int(4);
cout << (*A)[0]<< endl;
return 0;
}
new auto
int* y = new auto(3);
new与对象对齐
new在开辟内存的时候可以考虑到对齐信息
#include<iostream>
#include<new>
#include<vector>
using namespace std;
struct alignas(256) Str {};
int main()
{
Str* A = new Str;
cout << A<< endl;
return 0;
}
delete常见用法
销毁单一对象和单一数组
int* ptr = new int;
delete ptr;
int* pptr = new int[5];
delete[] pptr
placement delete
与placement new对应,只销毁对象但是不把资源返归还给系统
动态内存的相关问题
sizeof不会返回动态分配的内存大小
sizeof发生在编译器;vector的动态分配内存发生在运行期
allocator分配器分配内存
#include<iostream>
#include<new>
#include<memory>
#include<vector>
using namespace std;
void fun(int* x)
{
cout << "fun is called" << endl;
delete x;
}
int main()
{
allocator<int> al;
int* ptr = al.allocate(3);
int* y = new (ptr) int[3]{ 1,2,3 };
cout << *y+1 << endl;
return 0;
}
malloc/free管理内存
malloc只分配内存,但是没有对象的构造;
|