-
C/C++中程序内存区域划分
- 内核空间(用户代码不能读写)
- 栈(函数中存放的变量)
- 内存映射段
- 堆(重点)
- 数据段(静态区)全局变量 / 静态变量
- 代码段(常量区)
试分析下列代码
int globalVar = 1;// 这个变量globalVar 存放在静态区(原因:globalVar是全局变量)
static int staticGlobalVar = 1;//静态区 是静态变量
void Test()
{
static int staticVar = 1;//静态区,静态变量
int localVar = 1;// 栈区
int num1[10] = {1, 2, 3, 4};//num1存放在栈区,*num1存放在栈区
char char2[] = "abcd";//char2存放在栈区,*char2存放在栈区
这段代码是将"abcd"拷贝下来,开辟空间,放置在栈区
const char* pChar3 = "abcd";//PChar3存放在栈区,*pChar3存放在常量区
//这里解释一下pChar3 pChar3是const char* ,所指向的内容不能被修改
这段代码可以说明s存放的位置与t存放的位置一样
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);
}
-
C++中的new和delete(操作符)
C语言向堆上申请空间,使用malloc realloc calloc申请空间,放回首地址
C++使用new申请堆上的空间,返回首地址
new的好处
- 简洁
- 可以控制初始化
- 对于自定义类型,自动调构造函数
- 申请失败,会抛异常,无需手动检查
申请内置类型
#include<iostream>
using namespace std;
int main()
{
int* t = new int(1);//申请一个整形,并且将这个整形赋值为1
cout << *t << endl;
delete t;//释放这块空间
return 0;
}
申请内置类型数组
#include<iostream>
using namespace std;
int main()
{
int* arr = new int[10] { 1 };//申请10个整形的空间,第一个值赋为1,其余赋为0
delete[] arr;//释放空间
return 0;
}
申请自定义类型
下面演示抛异常:
#include <iostream>
using namespace std;
void func()
{
while (1)
{
int* temp = new int[1024 * 1024 * 100];
cout << temp << endl;
}
}
int main()
{
try
{
func();
}
catch (const exception& e)
{
cout << e.what() << endl;
}
return 0;
}
new的原理分析:
(这里不展开细讲,如果想知道其中细节,请在评论区私信我)
首先明确new是一个操作符,它是一个又operator new重载的运算符函数
operator new又是对malloc进行封装的函数
delete同样如此
delete的底层是operator delete
operator delete 的底层是free
定位new
显示调用构造函数,对一块已经有的空间初始化
使用方式 new ( 类的指针变量 ) 类名 (构造函数初始化的值)
举个例子:
#include <iostream>
using namespace std;
class A
{
public:
A(int a = 1 , int b = 2 )
{
_a = a;
_b = b;
}
void print()
{
cout << _a << " " << _b << endl;
}
private:
int _a;
int _b;
};
int main()
{
A* p = new A;
new(p)A(3,3);
p->print();
return 0;
}
函数模版
函数模版格式:
template < typename T1 , typename T2 ....... >
放回值类型 函数名 (参数列表)
#include <iostream>
using namespace std;
template <typename T>
void Swap( T& p1, T& p2)
{
T tmp = p1;
p1 = p2;
p2 = tmp;
}
int main()
{
int a = 1;
int b = 2;
Swap(a, b);//这里编译器会自动推断出T为int
cout << a << " " << b << endl;
return 0;
}
如何强制生成T为一个已知类型的函数
也就是显示实例化
在函数名与参数列表间加一个<T>(T为类型)
#include<iostream>
using namespace std;
template<typename T>
T Add(const T& p1, const T& p2)
{
return p1 + p2;
}
int main()
{
int a = 1;
double b = 2.2;
Add<int>(a, b);
return 0;
}
类模版
#include <iostream>
using namespace std;
template<typename T>
class Stack
{
public:
Stack()
{}
~Stack()
{
delete[] _arr;
_size = 0;
_top = 0;
_arr = nullptr;
}
void PushBack();
private:
T* _arr = new T[4];
int _size = 0;
int _top = -1;
};
template<typename T>
void Stack<T>::PushBack()// 这里Stack<T>是类型名
{
;
}
int main()
{
//同一个模版实例化两个对象
Stack<int> p1;// int类型的对象
Stack<double> p2; //double类型的对象
return 0;
}