请选择 进入手机版 | 继续访问电脑版
MSIPO技术圈 首页 IT技术 查看内容

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

2023-07-13

前面整理了两篇博客(C++ 基础知识 面试题(一)C++ 基础知识 面试题(二)

但发现这样整理很低效,所以还是打算做成问答题的形式。

Part 1是题目, Part2是答案。

Part 1

1.const修饰引用时,作用是什么?用于什么场景?

2.const修饰成员函数时,作用是什么?

3.const常量和宏定义有哪些区别?

4.static修饰普通变量时存储在哪里?特点是什么?

5.static修饰普通函数时,作用的什么?

6.static修饰成员变量时,什么时候可以在类内初始化?

7.static修饰成员函数时,可以访问类内所有成员吗?

8.static修饰成员变量和成员函数时有什么共同点?

9.this指针是什么?

10.inline内联函数是什么?什么情况下会默认为内联函数?

11.内联的优点和缺点是是什么?

12.虚函数可以是内联函数吗?

13.创建和删除子类对象时,是如何调用构造函数和析构函数的?

14.父类的析构函数为什么必须是虚函数?

15.volatile关键字声明的变量有什么特点?应用场景有哪些?

16.常量可以用volatile关键字修饰吗?指针可以用volatile关键字修饰吗?

17.assert()是什么?可以关闭吗?

18.用extern修饰变量,作用是什么?

19. extern "C" 的作用是什么?

20.当定义了一个结构体 struct Apple{...}, 声明这个结构体的时候,可以直接使用Apple a;而不是struct Apple a;吗?

Part2

1.const修饰引用时,作用是什么?用于什么场景?

一般用于形参,这样可以避免拷贝,同时函数无法对形参进行修改。

2.const修饰成员函数时,作用是什么?

作用是成员函数不能修改成员变量。

3.const常量和宏定义有哪些区别?

const常量是常量声明,由编译器处理,有类型安全检查,系统会分配内存,保存在数据段,一旦声明不能取消。

宏定义是字符替换,由预处理器处理,没有类型安全检查,系统不会分配内存,保存在代码段,可以用#undef取消。

4.static修饰普通变量时存储在哪里?特点是什么?

static普通变量存储在静态存储区。

特点是仅在第一次调用时初始化,并在程序的整个生命周期都保持初始化时的值。

5.static修饰普通函数时,作用的什么?

作用是表明该静态函数只能在定义该函数的文件中使用,防止与其他文件中的函数重名。

6.static修饰成员变量时,什么时候可以在类内初始化?

一般情况下,static修饰的成员变量只能在类外初始化。

除非该变量同时也是常量或者枚举类型。

7.static修饰成员函数时,可以访问类内所有成员吗?

静态成员函数只能访问静态成员。

8.static修饰成员变量和成员函数时有什么共同点?

静态成员变量和静态成员函数都是属于类的,而不是属于对象的。

都只有一个副本,只会被分配一次内存。

无需创建对象,直接使用类名就能调用。

9.this指针是什么?

this指针是隐含在每一个非静态成员函数中的特殊指针,指向调用该成员函数的对象。

10.inline内联函数是什么?什么情况下会默认为内联函数?

内联函数会在调用该函数的位置直接展开函数体。

在类内定义成员函数时,除虚函数以外的成员函数都会被默认为内联函数。

当在类外定义成员函数时,成员函数会被默认为非内联函数。

11.内联函数的优点和缺点是是什么?

优点是:

  • 节省开销;
  • 和宏定义相比,有类型检查,可以调用类的成员变量,在运行时可以调试。

缺点是:

  • 代码膨胀,如果内联函数使用频率高且函数体复杂,就会造成代码膨胀;
  • 如果函数库中用到了内联函数,在对函数库进行升级后,需要重新编译使用该函数库的代(因为用到内联函数的代码需要展开内联函数的函数体)。如果没有用到内联函数,那么就不需要重新编译所有使用该函数库的代码,只需要重新链接该函数库。
  • 是否内联,由编译器决定。即便显示使用了inline关键字,编译器也不一定会对函数内联。

12.虚函数可以是内联函数吗?

虚函数可以是内联函数。

但只有在不表现多态特性时,才会生效。

  • 譬如虚函数是通过类的具体对象来调用的:
  • A a = new A();
  • a.virtualFunc();

当虚函数表现多态特性了,即便定义虚函数时使用了inline关键字,内联也不会生效。因为内联是在编译器,而多态特性需要在运行期才知道调用哪个类的虚函数。

  • 譬如使用指针或者引用来调用虚函数:
  • A* a = new B();
  • a.virtualFunc();

13.创建和删除子类对象时,是如何调用构造函数和析构函数的?

创建子类对象时,一般现在子类构造函数中显式调用父类构造函数,然后再执行子类构造函数。

删除子类对象时,一般会先调用子类析构函数,再自动调用父类析构函数。

14.父类的析构函数为什么必须是虚函数?

当父类指针指向一个子类对象时,删除该对象,如果父类的析构函数不是虚函数,就会只调用父类的析构函数,不会调用子类的析构函数,造成内存泄漏。

如果父类的析构函数是虚函数,那么当删除该对象时,就会根据对象的实际类型取调用析构函数,这样子类对象就会得到正确释放。

15.volatile关键字声明的变量有什么特点?应用场景有哪些?

该变量的值有可能会在程序执行期间改变,所以编译器不能优化该变量(比如放入CPU寄存器中),而是只能从内存中读取。

因为使用volatile关键字会影响效率,所以最好是在有需要的时候才使用,比如硬件交互时、多线程编程时。

16.常量可以用volatile关键字修饰吗?指针可以用volatile关键字修饰吗?

可以。可以。

17.assert()是什么?可以关闭吗?

是宏。表示断言。如果assert()内的判断条件值为false,那么就会结束程序。

可以在#include<cassert>前协商#define DEBUG 来关闭断言。

18.用extern修饰变量,作用是什么?

表示在当前文件中,只是声明了改变量。编译器需要去别的文件中找到该变量的定义。

19. extern "C" 的作用是什么?

因为在C++中引入了函数重载的机制,所以编译器会对函数进行名称修饰,将参数类型也加到函数名的后面。而C语言没有这个特性。

所以在C++中使用C代码时,为了正确编译C代码,可以使用extern "C"{}来包括C代码,这样编译器就知道要用C语言的规则来编译这段代码。

20.当定义了一个结构体 struct Apple{...}, 声明这个结构体的时候,可以直接使用Apple a;而不是struct Apple a;吗?

当不存在一个同名的Apple()函数时,可以直接使用Apple a;来声明这个结构体。

但当存在一个c同名的Apple()函数时,只能使用struct Apple a;来声明这个结构体。

相关阅读

手机版|MSIPO技术圈 皖ICP备19022944号-2

Copyright © 2024, msipo.com

返回顶部