- 1. C/C++内存分布
- 2. C语言中动态内存管理方式
- 3. C++中动态内存管理
- 4. operator new与operator delete函数
- 5. new和delete的实现原理
- 6. 定位new表达式(placement-new)
- 7. 常见面试题
1. C/C++内存分布
为了方便管理内存被分为了以上的区域
我们来看下面的一段代码和相关问题
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";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
free(ptr1);
free(ptr3);
}
1. 选择题:
选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
globalVar在哪里?__(1)__ staticGlobalVar在哪里?__(2)__
staticVar在哪里?__(3)__ localVar在哪里?__(4)__
num1 在哪里?__(5)__
1.C:全局变量都在静态区
2.C:
3.C:用static修饰的局部变量也在静态区
4.A:局部变量都在栈上
5.A
char2 在哪里? ____ * char2 在哪里? ___pChar3 在哪里? ____ * pChar3 在哪里? ____ptr1在哪里?____ *ptr1在哪里?____
1. A:char2还是一个数组它就在栈上
2.A:*char2,数组名解引用结果是数组的第一个,所以还是在栈上
3.A:pchar3是一个指针类型所以也是在栈上
4.D:pChar它解引用是"abcd",通过解引用以后也无法对原来的数据进行修改,"abcd"本质就是代码段
5.A:也是一个指针类型,所以在栈上
6.B:malloc的都是在堆上
2. 填空题:
sizeof ( num1 ) = ____ ;sizeof ( char2 ) = ____ ; strlen ( char2 ) = ____ ;sizeof ( pChar3 ) = ____ ; strlen ( pChar3 ) = ____ ;sizeof ( ptr1 ) = ____ ;
sizeof(num1) = 40
sizeof数组名是整个数组的大小
sizeof(char2) =5
四个字符以外还有'\0',也是一个字符
strlen(char2)=4
sizeof(pChar3) = 8,32位下就是4,这里是一个指针的大小
strlen(pChar3) = 4
sizeof(ptr1) = 4
3. sizeof 和 strlen 区别?
sizeof
用于获取类型或对象的内存大小,包括字符串结束符。strlen
用于获取字符串的实际字符长度,不包括结束符。
2. C语言中动态内存管理方式:malloc/calloc/realloc/free
void Test ()
{
int* p1 = (int*) malloc(sizeof(int));
free(p1);
// 1.malloc/calloc/realloc的区别是什么?
int* p2 = (int*)calloc(4, sizeof (int));
int* p3 = (int*)realloc(p2, sizeof(int)*10);
// 这里需要free(p2)吗?
free(p3 );
}
3. C++内存管理方式
3.1 new/delete操作内置类型
int main()
{
int* p1 = (int*)malloc(sizeof(int));
int* p2 = new int;
free(p1);
delete p2;
}
这俩种写法是等价的
int main()
{
int* p1 = new int;
int* p2 = new int[10];
delete p1;
delete[] p2;
}
多个的这样写就行
还可以进行初始化
单个的用()括号进行初始化,多个的用{}用来初始化,没有初始化的部分全部初始化成0
注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和
3.2 new和delete操作自定义类型
class A
{
public:
A(int a=0,int b=0)
{
_a = a;
_b = b;
}
private:
int _a;
int _b;
};
int main()
{
A* p1 = new A;
A* p2 = (A*)malloc(sizeof(A));
}
可以看见一个会掉构造函数一个不会
甚至new的还可以用初始化列表的初始化方法来初始化
类的成员变量都是私有的那么在想去初始化就不行了
创建多个的话每一个都会调用构造函数和析构函数
多参数用{}就可以了
4. operator new与operator delete函数(重要点进行讲解)
4.1 operator new与operator delete函数(重点)
底层代码看不懂也没事
/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,
尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{
// report no memory
// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
/*
operator delete: 该函数最终是通过free来释放空间的
*/
void operator delete(void *pUserData)
{
_CrtMemBlockHeader * pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK); /* block other threads */
__TRY
/* get a pointer to memory block header */
pHead = pHdr(pUserData);
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg( pUserData, pHead->nBlockUse );
__FINALLY
_munlock(_HEAP_LOCK); /* release other threads */
__END_TRY_FINALLY
return;
}
/*
free的实现
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
new是操作符,malloc是函数,new底层其实就是封装malloc,new会调用构造函数,会抛出异常
5. new和delete的实现原理
5.1 内置类型
5.2 自定义类型
- new的原理
- delete的原理
- new T[N]的原理
- delete[]的原理
通过汇编可以看到这里用了44字节的内存,10个整形应该是40字节啊,多的4的字节拿去干嘛了?
多的4的字节拿来保存10了,这里是为了析构函数
delete[]里面就是缺省的上面的10,这里就会调用10次析构函数
改变参数,可以发现这里跟着改变了
delete[]向前偏移数,这里多的4的字节就是对象个数,方便delete去,知道有多少个对象去调用析构函数
这里可以得出一个结论,malloc就和free配套使用,new就和delete使用,要不然可能会有各种各样的问题
6. 定位new表达式(placement-new) (了解)
class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
// 定位new/replacement new
int main()
{
// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行
A* p1 = (A*)malloc(sizeof(A));
new(p1)A; // 注意:如果A类的构造函数有参数时,此处需要传参
p1->~A();
free(p1);
A* p2 = (A*)operator new(sizeof(A));
new(p2)A(10);
p2->~A();
operator delete(p2);
return 0;
}
7. 常见面试题
7.1 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在释放空间前会调用析构函数完成空间中资源的清理