谁有专门做外挂的网站百度竞价渠道代理
文章目录
- 存储方案的概念不适用于动态内存
- 编译器使用三块独立的内存
- 释放new分配的内存的最佳方案:delete
- new分配内存同时也可以初始化(用圆括号或花括号(列表初始化))
- 单值变量
- 数组
- 结构
- 有合适构造函数的类
- new和delete运算符调用的函数:分配函数和释放函数(运算符重载)
- 定位new运算符,指定使用的内存位置
- 示例 定位new分配的内存不一定是动态的堆内存,所以不能用delete释放
存储方案的概念不适用于动态内存
前面讲了存储持续性,作用域,链接,和用这三个概念区分的5种存储方案:
但是这5种方案没有包含动态内存的处理方式。
即C中malloc函数分配的内存,或者C++的new运算符分配的内存。这些动态内存都用堆的方式来使用内存,即分配和释放的顺序不再像栈那样先进后出,而是取决于new和delete。
动态内存不受存储持续性,作用域,链接的规则控制,而是完全由new 和 delete控制。
编译器使用三块独立的内存
C中说过了,编译器会使用三块独立的内存:
一块专门存静态变量,内部还可以再细分;
一块专门用于自动变量,以栈的方式管理;
一块专门用于动态存储,用new和delete管理(C用malloc函数和free函数管理);
虽然存储方案的概念不适用于动态内存,可是适用于指向这些动态内存的指针呀。指针变量是有自己的存储持续性,作用域和链接的。
比如
//分配了20个float类型的位置,即80字节,pt是一个指针,指向第一个元素
//当声明这句代码的块执行完以后,失去了pt,想delete这块内存也delete不掉了,所以需要的话要把这段内存的地址传给别的函数
float * pt = new float[20];
释放new分配的内存的最佳方案:delete
别想着依赖操作系统,靠人不如靠己
new分配内存同时也可以初始化(用圆括号或花括号(列表初始化))
new从堆heap里找内存
就是不能用方括号,因为方括号里的数值表示分配的数目
单值变量
用花括号实际上是把列表初始化用于单值变量
int *pi = new int (10);//把*pi初始化为10
int *pi = new int {10};//同上double *pd = new double (99.99);//把*pd初始化为99.99
double *pd = new double {99.99};//同上
数组
new的同时初始化数组,同时用方括号和大括号,不用赋值运算符,因为是列表初始化
int * p_ar = new int[5] {10, 20, 30, 40, 50};
结构
new的同时初始化结构
struct where
{double x;double y;double z;
};
where * one = new where {1.2, 8.1, 12.5};
有合适构造函数的类
new和delete运算符调用的函数:分配函数和释放函数(运算符重载)
定位new运算符,指定使用的内存位置
之前用new请求内存,不能指定具体在哪块内存分配动态内存给动态变量用。于是C++推出了new运算符的一个变体:定位new运算符。
很简单,跟以前相比只是需要在new屁股后面加一个圆括号说明内存位置就行,并且要包含头文件new。、
示例 定位new分配的内存不一定是动态的堆内存,所以不能用delete释放
之前一直在强调new和delete的配合搭配,使劲强化一定不要忘记delete的记忆,现在竟然不用delete了,不错呀
但是我们也要明白,不用释放是因为我们指定的内存一般都是静态内存或者自动内存,因为你只有定义了才能指定呀,我们自己定义的变量使用的内存肯定不是动态内存,所以无需delete释放。你要用就用,但是不用释放,他们的释放还是按照自己的存储持续性来存在和消亡。
#include <iostream>
#include <new>
const int BUF = 512;
const int N = 5;
char buffer[BUF];//chunk of memory内存块,
//注意buffer是静态数组,所以存在静态内存,而非堆内存
//所以不能用delete释放,因为delete只能释放动态内存(位于堆)int main()
{using std::cout;using std::endl;cout << "Calling new and placement new:\n";double * p1, * p2;p1 = new double[N];//use heap//把动态数组分配在buffer数组处p2 = new (buffer) double[N];//use static array bufferint i;for (i = 0; i < N; ++i)p1[i] = p2[i] = 20.0 * i + 1000;cout << "Memory addresses:\n" << "heap: " << p1<< " static: " << (void *)buffer << endl;//用void *强制转换使之显示地址,//否则由于buffer是char *,会显示字符串cout << "Memory contents:\n";for (i = 0; i < N; ++i){cout << p1[i] << " at " << &p1[i] << "; ";cout << p2[i] << " at " << &p2[i] << endl;}cout << "\nCalling new and placement new a second time:\n";double * p3, * p4;p3 = new double[N];//use heapp4 = new (buffer) double[N];//use static array bufferfor (i = 0; i < N; ++i)p3[i] = p4[i] = 20.0 * i + 2000;cout << "Memory contents:\n";for (i = 0; i < N; ++i){cout << p3[i] << " at " << &p3[i] << "; ";cout << p4[i] << " at " << &p4[i] << endl;}//还是用p1和p2,但是重新分配地址cout << "\nCalling new and placement new a third time:\n";delete [] p1;p1 = new double[N];//use heapp2 = new (buffer + N * sizeof(double)) double[N];//use static array bufferfor (i = 0; i < N; ++i)p1[i] = p2[i] = 20.0 * i + 3000;cout << "Memory contents:\n";for (i = 0; i < N; ++i){cout << p1[i] << " at " << &p1[i] << "; ";cout << p2[i] << " at " << &p2[i] << endl;}delete [] p1;delete [] p3;return 0;
}
可以看到,
- 堆内存和静态内存相隔遥远,印证了编译器使用了独立的内存块来存储静态变量,自动变量和动态变量。
- 当我释放了p1后,再次用new分配,还是分配了一样的地址:第一次和第三次都是0xac6cb0,这说明我的编译器在实现上可能是把一段内存作为动态堆,需要动态分配就先按顺序分配,每次都从0xac6cb0开始。这是我的猜测,且这个也不重要,具体怎么样是看编译器的实现。
- 定位new只会分配指定位置,第二次调用时,buffer数组那里的100-1080就被覆盖了。
Calling new and placement new:
Memory addresses:
heap: 0xac6cb0 static: 0x4c7020
Memory contents:
1000 at 0xac6cb0; 1000 at 0x4c7020
1020 at 0xac6cb8; 1020 at 0x4c7028
1040 at 0xac6cc0; 1040 at 0x4c7030
1060 at 0xac6cc8; 1060 at 0x4c7038
1080 at 0xac6cd0; 1080 at 0x4c7040Calling new and placement new a second time:
Memory contents:
2000 at 0xaca4d8; 2000 at 0x4c7020
2020 at 0xaca4e0; 2020 at 0x4c7028
2040 at 0xaca4e8; 2040 at 0x4c7030
2060 at 0xaca4f0; 2060 at 0x4c7038
2080 at 0xaca4f8; 2080 at 0x4c7040Calling new and placement new a third time:
Memory contents:
3000 at 0xac6cb0; 3000 at 0x4c7048
3020 at 0xac6cb8; 3020 at 0x4c7050
3040 at 0xac6cc0; 3040 at 0x4c7058
3060 at 0xac6cc8; 3060 at 0x4c7060
3080 at 0xac6cd0; 3080 at 0x4c7068