1.在main执行之前和之后执行地代码可能是什么?
main函数执行之前,只要是初始化系统相关资源:
- 设置栈指针
- 初始化静态static变量和global全局变量,即.data段的内容
- 将未初始化部分的全局变量赋初值
- 全局对象初始化,在main之前调用构造函数
- 在main函数的参数argc,argv等传递给main函数,然后才真正运行main函数
__attribute__((constructor))
main函数执行之后:
- 全局对象的析构函数会在main函数之后执行
- 可以用
atexit
注册一个函数,它会在main之后执行 __attribute__((destructor))
__ attribute__
可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。
2.指针和引用
2.1区别
- 指针是一个变量,存储的是一个地址,引用跟原来的变量实质上是同一个东西,是原来的别名
- 指针可以多级,引用只能一级
- 指针可以为空,引用不能为NULL且要在定义时初始化
- 指针在初始化后可以改变指向,而引用在初始化后不可改变
- sizeof指针得到的是本指针的大小,sizeof引用得到的是引用所指向变量的大小
- 当把指针作为参数进行传递时,也是将实参的一个拷贝传递给形参,两者指向的地址相同,但不是同一个变量,在函数中改变这个变量的指向不影响实参,而引用却可以。
- 引用本质是一个指针,同样会占4字节内存;指针是具体变量,需要占用存储空间
2.2在传递函数参数时,什么时候用指针,什么时候用引用?
- 需要返回函数内局部变量的内存的时候用指针。使用指针传参需要开辟内存,用完要记得释放指针,不然会内存泄漏。而返回局部变量的引用是没有意义的
- 对栈空间大小比较敏感(比如递归)的时候使用引用。使用引用传递不需要创建临时变量,开销要更小
- 类对象作为参数传递的时候使用引用,这是C++类对象传递的标准方式
2.3区别一下指针类型
int *p[10]; //表示指针数组,是一个数组变量,存放着10个指针
int (*p)[10]; //表示数组指针,是一个指针指向一个大小为10的数组
int *p(int); //函数声明,参数是int类型的,返回值是int*类型的
int (*p)(int); //函数指针,指针指向一个函数
3.new/delete 与 malloc/free
3.1 区别
- 属性: new和delete是C++关键字,需要编译器支持;malloc和free是库函数,需要头文件支持
- 参数: 使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算,而malloc则需要显示地指出所需内存的尺寸
- 返回类型:new操作内存分配成功时,返回地时对象类型地指针,无须进行类型转换,而malloc内存分配成功返回的时void*类型,需要通过类型转换将void *指针转换成我们需要的类型。
- 自定义类型new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
- 重载:C++允许自定义operator new 和 operator delete 函数控制动态内存的分配。
- 内存区域:new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。
- 分配失败:new内存分配失败会抛出bac_alloc异常;malloc会返回null
- 内存泄漏: 内存泄漏对于new和malloc都能检测出来,而new可以指明是哪个文件的哪一行,malloc确不可以。
引用:https://blog.csdn.net/nyist_zxp/article/details/80810742
3.2被free回收地内存是立即返回给操作系统吗?
不是的,被free回收的内存会首先被ptmalloc使用双链表保存起来,当用户下一次申请内存的时候,会尝
试从这些内存中寻找合适的返回。这样就避免了频繁的系统调用,占用过多的系统资源。同时ptmalloc
也会尝试对小块内存进行合并,避免过多的内存碎片。
4 C++和其他语言的区别
4.1 C++和Python的区别
4.2 C++和C语言的区别
4.3 C++和JAVA的区别
5.static关键字
5.1作用
- 修饰全局变量时,表明一个全局变量只对定义在同一文件中的函数可见
- 修饰局部变量时,表明该变量的值不会因为函数终止而丢失
- 修饰函数时,表明该函数只在同一文件中调用
- 修饰类的数据成员,表明对类所有对象这个数据成员都只有一个实例。
- 修饰类的成员函数,静态成员函数只能访问它的参数、类的静态数据成员和全局变量
c++中static的作用
6 const关键字
- const 修饰基本类型数据类型
- const 修饰指针变量和引⽤变量
- 作为参数的 const 修饰符:调⽤函数的时候,⽤相应的变ᰁ初始化 const 常ᰁ,则在函数体
中,按照 const 所修饰的部分进⾏常ᰁ化,保护了原对象的属性。 - 作为函数返回值的 const 修饰符:声明了返回值后,const 按照"修饰原则"进⾏修饰,起到相应的保护作⽤
- const 成员变量,只在某个对象⽣命周期内是常量,⽽对于整个类⽽⾔是可以改变的。因为类可以创建多个对象,不同的对象其 const 数据成员值可以不同。所以不能在类的声明中初始化 const 数据成员,因为类的对象在没有创建时候,编译器不知道 const 数据成员的值是什么。const 数据成员的初始化只能在类的构造函数的初始化列表中进⾏。
- const 成员函数:const 成员函数的主要⽬的是防⽌成员函数修改对象的内容。const 关键字和 static 关键字对于成员函数来说是不能同时使⽤的,因为 static 关键字修饰静态成员函数不含有 this 指针,即不能实例化,const 成员函数⼜必须具体到某⼀个函数
- const 修饰类对象,定义常量对象:常量对象只能调⽤常量函数,别的成员函数都不能调⽤