变量所在哪个内存区域以及变量所占空间大小
int globalVar = 1;//数据段(静态区)
static int staticGlobalVar = 1;//数据段(静态区)
void Test()
{
static int staticVar = 1;//数据段(静态区)
int localVar = 1; //栈
int num1[10] = {1, 2, 3, 4}; //栈
char char2[] = "abcd"; //char2 *char2 在"栈"中
const char* pChar3 = "abcd"; //pChar在"栈"中,*pChar在"代码段(常量区)"
int* ptr1 = (int*)malloc(sizeof (int)*4); //ptr1在"栈"中 *ptr1在"堆"中
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
free (ptr1);
free (ptr3);
}
所在内存区:
golobalVar、staticGlobalVar、staticVar都是在“数据段(静态区)”中,因为前两个是全局变量,全局变量都在静态区,后面一个是static静态类型,也在静态区。
普通的变量localVar和数组num1函数结束后释放,都在“栈”中;数组char2[]只是动态大小,初始化完成后和num1一样在“栈”中;*char2也在“栈”中,char2[]在栈中开辟了5个字节,把常量“abcd”拷贝过去,所以*char2是栈中的“a”。
pChar3是局部指针变量,在“栈”中,又因为pChar3指向的是常量区“abcd”,所以*pChar3在“代码段(常量区)”。
ptr1,ptr2,ptr3都是局部指针变量,都是在“栈”上,*ptr1指向的空间是在“堆”上开辟的。
所占空间大小:
sizeof(num1) = 40;
sizeof(char2) = 5; strlen(char2) = 4;
sizeof(pChar3) = 4或8 //根据系统可能是4可能是8;
strlen(pChar3) = 4;
sizeof(ptr1) = 4或8;
申请动态空间new/delete
malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:
1. malloc和free是函数,new和delete是操作符
2.malloc申请的空间不会初始化,new可以初始化
3.malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,如果是多个对象,[]中指定对象个数即可
4. malloc的返回值为void*,在使用时必须强转,new不需要,因为new后跟的是空间的类型
5.malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
6.申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
7.malloc和free,new和delete最好配套使用,不然会有意想不到的错误
#include <iostream>
using namespace std;
class A
{
public:
A(int a=0)
:_a(a)//初始化列表
{
cout<< "A()" <<endl;
}
~A()
{
cout<< "~A()" <<endl;
}
private:
int _a;
};
int test1()//动态空间 new
{
int* p1=new int; //申请一个int不会初始化
int* p2=new int(20);//一个int初始化为20
int* p3=new int[10];//申请10个int的数组
int* p4=new int[10]{1,2,3};//数组初始化
delete p1;//free p1
delete p2;//
delete[] p3;//free数组p3 p4
delete[] p4;
//new/delete和malloc/free的区别就是new/delete会调用构造和析构函数
A* a1=new A(); //调用构造函数
delete a1; //先调用析构函数 再释放空间
A* a2=new A[3]; //调用3次构造函数
delete[] a2; //先调用析构函数 再释放空间
A* a3=(A*)malloc(sizeof(A));
if(a3== nullptr) perror("malloc fail");
new(a3)A(20);//定位new 初始化已有空间
a3->~A();
free(a3);
return 0;
}
泛型编程--模版
模版是让编译器去产生特定类型函数的模具,Debug过程中看似用的是一个函数,实则汇编中用的是编译器产生的对应类型的函数
格式:template<typename 自定义名1 , typelate 自定义名2 , ......>,也可以使用class代替typename
定义过template后只有第一个函数生效模版。
显示实例化:当一个函数中要用两个不同类型的实参:
函数名<类型>(实参1 , 实参2 , ....)
//template<class T>
template<typename T>
void Swap(T& x,T& y)
{
T tmp=x;
x=y;
y=tmp;
}
template<typename A>
A ADD(const A& x,const A&y)
{
return x+y;
}
int test2()//泛型编程--模版
{
//模版是让编译器去产生特定类型函数的模具
int a=10,b=20;
Swap(a,b);//看似是用同一个函数,汇编中用的不是一个
double c=30,d=40;
Swap(c,d);
cout << ADD(a,b) << endl;
cout << ADD(c,d) << endl;
//显示实例化
cout << ADD<int>(a,c) << endl;
cout << ADD<double>(d,b) << endl;
return 0;
}
类也可以使用模版
template<class S>
class Stack
{
public:
Stack(int capacity=4)
{
_a=new S[capacity];
_top=_capacity=0;
cout<< "Stack()" << endl;
}
~Stack()
{
delete[] _a;
_capacity=_top=0;
cout<< "~Stack()" << endl;
}
private:
S* _a;
size_t _top;
size_t _capacity;
};
int test3()//显示实例化--不同类型栈
{
Stack<int> st1;
Stack<double> st2;
return 0;
}