【C++入门】内存管理(1)
目录
4.malloc和operator new 和 new的区别
1.做题目,内存分区
数据段(静态区):存放全局或者静态变量;

解:
globalVar是全局变量,在数据段(静态区),选C;
staticGlobalVar是全局静态变量,在数据段(静态区),选C;
staticVar是局部静态变量,在数据段(静态区),选C;
这三个变量的区别是,它们的生命周期是整个程序运行期间;声明的时候globalvar是第一个,staticGlobalVar是第二个,staticVar是第三个;
globalvar是在所有文件都可见,一旦包含了这个文件,此时包含这个文件的那个文件如果起了同名的变量,就会出现问题;
staticGlobalVar只会在本文件中可见,其他文件即使包含这个文件,也不会访问到这个文件。
localvar是局部变量,在栈上,选A;
num1是一个数组,40个字节,10个元素,在栈上,选A;
char2是一个数组,5个字节,包含\0,5个元素,存在栈上,选A;
*char2是数组的第一个元素,数组在栈上,那么首元素也一定在栈上,选A;
pChar3是一个局部变量,指针,32位cpu就4个字节,在栈上,选A;
*pChar3保存的是字符串首元素的地址,而字符串是在常量区(代码段),选D;
ptr1是一个局部指针,在栈上,选A;
*ptr由于是malloc开辟的空间,所以在堆上,选B;



2.malloc/calloc/realloc区别
malloc:申请空间;
calloc:申请空间+将每一个空间初始化为0;
realloc:对原来的空间进行扩容;
3.C++申请内存的方式
C++使用操作符new,就能开辟空间,返回这个类型的指针;
销毁函数的时候使用delete操作符进行内存的回收;
使用new还能对空间进行初始化具体如下:

3.1 new/delete的作用
对于基本类型,和c语言的malloc和free没有任何区别,唯一的区别是自定义类型,例如:

当使用new的时候,会调用类的构造函数,默认将a初始化为0;而c语言本质只会申请空间,c++不仅可以申请空间,还能调用构造函数进行初始化;

free函数和delete函数同理:

free函数只是释放空间,delete不仅能释放空间,还能调用析构函数;
4.malloc和operator new 和 new的区别
malloc只会创建内存;
operator new 创建内存 + 创建失败抛异常; 等同于malloc + 失败抛异常;
new 创建内存 + 创建失败抛异常 + 调用构造函数;等同于 malloc + operator new + 调用构造函数;
注意:这里创建所有的空间都是在堆上进行的,速度比较慢,后面学到内存池,会有另一种方法;
面试题:malloc 和new的区别?
1.new 会调用构造函数,内存创建失败了会抛异常;malloc失败了会返回0;
2.malloc是一个函数;new是一个操作符;
3.malloc用法:参数传入字节数,返回值是void*,new后面跟申请对象的类型,返回值是该类型的指针;
5.定位new
当只想在已有的空间调用构造函数进行初始化,该如何操作?
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class A
{
private:
int a;
public:
A() {};
A(int val):a(val)
{}
~A(){}
};
int main()
{
A* pn = new A(10);
// 下面两步等同于上面一步
A* p = (A*) operator new(sizeof(A)); // 仅分配内存,不调用构造函数
new(p)A(10); // 对已经存在的空间调用构造函数初始化
p->~A();
operator delete(p);
return 0;
}
1.首先使用operator new分配空间,此时并没有调用构造函数进行初始化;
2.使用定位new,即 new(已经分配好空间的指针)A(构造形参);
3.此时就完成了new的功能,即分配内存空间并调用构造函数进行初始化;
6.内存泄漏问题
在java中基本很少存在这个问题,因为存在一个垃圾回收机制。
6.1 什么是内存泄露?
下面的代码申请了1G字节的空间,但是在使用完毕之后没有释放,此时其他人想要使用这块内存,是无法使用的的,因为已经被占用了,这就叫内存泄露;糙一点说就是,占着茅坑不拉屎;
char* p = new char[1024*1024*1024];
如果长期运行的进程,如果每次执行一个任务会导致内存泄露,最后会导致程序崩溃;
valgrind是可以检测内存泄露的一个小工具,可以了解一下;
如何规避内存泄露呢?一个就是写代码的规范问题,还有一个就是可以使用c++11的智能指针,这在后面的部分会介绍到。
面试题:如何在堆上申请4G的空间?
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
// 堆上申请4G内存空间?
int main()
{
size_t n = 4; // 这里不用int的原因是,int会溢出
try
{
void* p = new char[n * 1024 * 1024 * 1024]; // 此时会报错
cout << "new :" << p << endl;
}
catch (exception& e)
{
cout << e.what() << endl;
}
}
由于进程地址空间不够大,所以程序会崩溃;从原来的2^32次方到了2^64次方(40亿个4G),只需要将平台从32位换到64位使进程空间地址变大;
更多推荐

所有评论(0)