C++ 基础知识 问答题(四)

Part1

1.深拷贝是什么?浅拷贝是什么?

2.new与malloc有什么区别?

3. 重载是什么?重定义(隐藏)是什么?重写是什么?

4.协变是什么?

5.const修饰成员函数的作用是什么?

6.拷贝构造函数会造成内存泄漏吗?

7.指针和引用的区别?

8.基本数据类型在32和64位操作系统中所占据的字节数有什么不同?

9.定义对象有哪些方法?

10.哪些函数不能为虚函数?

11.序列式容器的迭代器会在什么情况下失效?

12.关联式容器的迭代器会在什么情况下失效?

13. struct的大小如何计算?

14. 空类的大小是多少?当一个派生类继承了空类,计算派生类大小时,需要加入空类的大小吗?

15.计算class大小时需要考虑哪些成员?

16.当存在继承、多继承、虚继承的情况时,如何计算class的大小?

17.#pragma pack(n)如何设定对齐方式?

18.map的底层实现是什么?

19.unordered_map的底层实现是什么?

20.虚函数表是属于类的还是属于类对象?虚函数表指针是属于类的还是属于类对象?

21.一个类多继承N个类,该类中有多少个虚函数表指针?

22.虚函数的作用是什么?

23.派生类中声明基类的同名虚函数时,需要加virtual吗?

24.public、protected和private的访问权限是什么?

Part2

1.深拷贝是什么?浅拷贝是什么?

深拷贝:原来的对象和拷贝对象相互独立,会复制变量指向的动态分配的内存,修改其中一个对象,不会影响另一个对象。

浅拷贝:原来的对象和拷贝对象共用一份实体,不会复制变量指向的动态分配的内存,修改其中一个对象,会影响另一个对象。

系统默认为一个类生成的拷贝构造函数,执行的是浅拷贝

2.new与malloc有什么区别?

newmalloc
操作符函数
不需要指定内存的大小(字节数),根据类自动生成需要指定内存的大小(字节数)
失败时抛出异常失败时返回NULL
先申请内存,再调用构造函数只申请内存
底层可以用malloc实现不能用new实现
不可以二次分配内存可以用realloc二次分配内存(扩大或缩小)
自由存储区
返回具体类的类型的指针返回void*
允许重载不允许重载
针对数组,有new A[10]不特别处理数组

3. 重载是什么?重定义(隐藏)是什么?重写是什么?

重载:在同一作用域下,函数名相同,函数参数不同。编译器根据函数的参数类型,来决定调用哪个函数。(返回值类型不构成重载)。

重定义(隐藏):不同作用域下(父类和子类中),函数名相同,当子类的对象调用同名函数时,默认调用子类的函数,隐藏父类的函数,除非加上了父类的域作用符 :: 。

重写:父类的函数用virtual修饰,子类中一函数,函数名相同、函数参数类型相同、返回值相同,则构成重写。(唯一的例外是返回值协变)。如果父类函数是const,子类函数可以是const,也可以不是const。如果如果父类函数不是const,子类函数只能不是const在。

4.协变是什么?

子类重写父类的函数,当父类函数的返回值类型是指针或引用时,子类的返回值可以是父类函数返回值类型的子类。

5.const修饰成员函数的作用是什么?

const成员函数不能修改成员变量 (mutable除外),只能调用其他const成员函数

6.拷贝构造函数会造成内存泄漏吗?

默认的拷贝构造函数是浅拷贝,会导致析构时,同一资源被释放两次。

7.指针和引用的区别?

指针引用
指针是一个变量,占据内存 空间引用是一个别名,不占据内存空间
可以为NULL,且非const指针可以改变值不能为NULL,必须初始化,初始化后不能改变值
指针++,是指针地址自增引用++,是引用绑定的对象的自增
sizeof(指针),得到指针大小sizeof(引用),得到引用绑定的对象的大小
作为函数参数传递时,指针实际上是传值,对指针形参的改变,不会改变指针实参的值。需要通过*指针来改变指针指向的内存的值。作为函数参数传递时,引用实际上是引用传递,传的是实参,对形参的改变会改变实参。

8.基本数据类型在32和64位操作系统中所占据的字节数有什么不同?

32位操作系统64位操作系统
int44
long48
long long88
float44
double88
指针48
short22
char11

9.定义对象有哪些方法?

在栈上定义,A a; 由编译器管理内存,当超出作用域,对象被自动销毁。

在堆上定义,A* a = new A(); 由程序员管理内存,允许对象的生命周期超出变量所在的作用域,需要程序员手动释放内存。

10.哪些函数不能为虚函数?

静态函数、非成员函数、构造函数、友元函数

11.序列式容器的迭代器会在什么情况下失效?

插入或删除元素后,指向插入或删除元素位置之后的迭代器全部失效。(需要更新迭代器,比如 it = nums.erase(it))

容器的容量capacity变化时(比如插入元素,原有的capacity不足,重新分配内存),迭代器会失效

12.关联式容器的迭代器会在什么情况下失效?

插入或删除元素后,指向插入或删除元素位置的迭代器失效。其他迭代器不受影响,因为关联式容器的底层结构是红黑树。(为了解决当前迭代器失效的问题,可以在删除或插入前自增迭代器)

13. struct的大小如何计算?

计算结构体的大小要考虑到内存对齐,主要是两个原则:

1)每个成员变量的偏移量是成员变量大小的整数倍,比如int是4字节,可以放在0,4,8,12等地址,但不能放在2,3,5等地址。

2)结构体的大小必须是所有成员变量的大小的整数倍,也就是所有成员变量大小的最小公倍数。

14. 空类的大小是多少?当一个派生类继承了空类,计算派生类大小时,需要加入空类的大小吗?

空类的大小为1。

当一个派生类继承了空类,计算派生类大小时,不需要加入空类的大小。

但当空类作为非静态成员变量时,需要计算大小(为1)。

15.计算class大小时需要考虑哪些成员?

考虑非静态成员变量。

不考虑静态成员和成员函数。

16.当存在继承、多继承、虚继承的情况时,如何计算class的大小?

当存在继承时,若父类中有虚函数,计算class大小时,需要加父类的大小,和一个虚表指针(4字节),指向包含了父类和子类所有虚函数的虚表。

当存在多继承,例如继承了N个类,且父类中都有虚函数,那么需要加N个父类的大小,和N个虚表指针,各指向包含了父类所有虚函数的虚表,其中第一个虚表包含了第一个继承的父类的虚函数和子类的虚函数。

当存在虚继承,需要加父类的大小,和一个指向派生类的虚表的虚表指针,一个指向基类的虚表的虚基表指针。

17. #pragma pack(n)如何设定对齐方式?

n可以是2的幂:1,2,4,8...

成员对象对齐时,取成员变量大小和n中的较小值来对齐,偏移量是min(成员变量大小,n)的倍数

计算class的整体大小时,取最大的成员变量的大小和n中的较小值来对齐,class大小是min(最大的成员变量大小,n)的倍数。

18.map的底层实现是什么?

红黑树。红黑树是平衡二叉查找树的一种变体,并不严格保证左右子树高度差<=1,但是平衡的代价更低,平均性能强于平衡二叉树。

红黑树是一棵二叉查找树,且满足以下性质:

  • 结点是黑色或红色。
  • 根节点是黑色。
  • 叶子结点为NULL,是黑色。
  • 红色结点的子节点颜色为黑色。
  • 任意结点到其叶子结点都有相同数量的黑色结点。

关键性质:从根结点到叶子结点的最长路径不会大于最短路径的两倍。

19.unordered_map的底层实现是什么?

哈希表。哈希表实现为一个动态数组,每个元素是一个桶,存储着一个链表或者红黑树。

20.虚函数表是属于类的还是属于类对象?虚函数表指针是属于类的还是属于类对象?

虚函数表是属于类。

虚函数表指针是属于类对象。

21.一个类多继承N个类,该类中有多少个虚函数表指针?

若N个类中有M个类有虚函数,那么派生类中会有M个虚函数表指针,指向M个不同的虚函数表。

22.虚函数的作用是什么?

允许在派生类中重新定义与基类同名的函数,并通过基类的指针或引用来访问派生类中的同名函数。

23.派生类中声明基类的同名虚函数时,需要加virtual吗?

可加可不加,因为派生类中与基类同名的函数会默认是virtual

24.public、protected和private的访问权限是什么?

public:类内外和派生类都可以访问,在类的对象中可见。

protected:类内和派生类可以访问,在类的对象中不可见。

private:只有类内可以访问,在类的对象中不可见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值