C/C++ 面试知识点2

7.浅拷贝和深拷贝的原理

浅拷贝(位拷贝)就是两/多个对象共享一块内存,其缺点就是当析构一个对象的时候,另一个对象也不存在了,如果再使用它就会发生错误。

同一块资源释放多次,崩溃或者内存泄漏

 

深拷贝就是完完全全的复制出一个对象,两者在内存上无任何关系。

必须显式提供拷贝构造函数和赋值运算符

缺省拷贝构造函数在拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标--浅拷贝。

 

 

8.常见的不能声明为虚函数的有哪些?

普通函数(非成员函数)

静态成员函数

内联成员函数

构造函数

友元函数

9.C++的静态多态和动态多态

静态多态:运行前确定类型,采用的是函数重载和泛型

动态多态:运行后确定类型或者函数调用,采用虚函数实现

 

10.C++虚函数的原理

 

11.C++虚函数占用类的大小

因为只需要维护一个指向虚表的指针,所以大小为4或8个字节 
静态成员和函数不计入sizeof中。

 

12.new与malloc的区别

new与malloc的10点区别

  • 1. 申请的内存所在位置 :new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从上动态分配内存。
  • 自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区
  • 自由存储区是否能够是堆(问题等价于new是否能在堆上动态分配内存),这取决于operator new 的实现细节。
  • 自由存储区不仅可以是堆,还可以是静态存储区,这都看operator new在哪里为对象分配内存
  • malloc函数从上动态分配内存, 堆是操作系统中的术语,是操作系统所维护的一块特殊内存,
  • 用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。
  • 2.返回类型安全性
  • new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换
  • malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
  • 3.内存分配失败时的返回值
  • new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL。
  • 4.是否需要指定内存大小
  • 使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算,而malloc则需要显式地指出所需内存的尺寸。
  • 5.是否调用构造函数/析构函数
  • 使用new操作符来分配对象内存时会经历三个步骤:
  • 调用operator new 函数,分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象。
  • 编译器运行相应的构造函数以构造对象,并为其传入初值
  • 对象构造完成后,返回一个指向该对象的指针
  • 使用delete操作符来释放对象内存时会经历两个步骤:

    • 第一步:调用对象的析构函数
    • 第二步:编译器调用operator delete(或operator delete[])函数释放内存空间。

    总之来说,new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构。而malloc则不会

13.C++中有哪几种数据存储区?

栈、堆、自由存储区、全局/静态存储区、常量存储区

 

14.什么是栈溢出?哪些情况下比较容易出现栈溢出?

栈溢出泛指系统维护的栈溢出,因数据压不下去了,导致溢出,此时程序会崩溃。

一般递归深度过大、创建普通数组过大(就是局部变量占用的空间大于栈了就会溢出new的是堆,不算)。

15.“#include”后面跟引号与尖括号的区别?

引号编译器会搜索当前工作目录下的头文件,尖括号会搜索安装目录下的头文件

16.gcc和g++的区别

gcc和g++都是GNU(组织)的一个编译器

编译阶段,g++会调用gcc, 但是gcc命令不能自动和C++程序使用的库链接,所以为了统一,干脆编译/链接统统用g++了

 

17.类成员函数的重载、覆盖和重写区别

重载和普通的函数重载一样。
覆盖则基类的函数要加virtual (这就是多态的实现
如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏,子类就重写了这个函数
如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏,子类就重写了这个函数

18.构造函数为什么不能是虚函数

虚函数存在于虚表中,而虚表要靠虚表指针维护,而只有实例化后的对象才有虚表指针

实例化对象就必须调用构造函数初始化对象,所以冲突了,结果就是构造函数不能是虚函数。

19. printf(“%d,%d\n”,i++,i++),若i=0,则结果输出什么。

这里有一个点就是,printf和cout输出的时候都是从右至左读取值,所以结果应该是1,0。

 

posted on 2018-12-28 19:11  积跬步306  阅读(168)  评论(0编辑  收藏  举报