ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【面试题】【C++】01-C++语法部分面试题

2022-02-04 12:34:40  阅读:119  来源: 互联网

标签:面试题 01 const 区别 C++ 引用 ptr 指针


【面试题】【C++】01-C++语法部分面试题

1 C和C++有什么区别?

  1. 和C语言相比,C++新增了面向对象的内容。C语言主要使用面向过程的编程范式,C++主要使用面向对象的编程范式(泛型编程和函数式编程使用相对较少);
  2. 和C语言相比,C++新增了引用、函数重载、异常处理、内联函数等功能;
  3. C++用new/delete替代了C语言中的malloc/free,此外还添加了智能指针,在动态内存的使用上安全性更高。

2 以下代码中的a和&a有什么区别?

int a[10];
int (*p)[10] = &a;
  1. a是数组名,也是数组的首地址。a+1会向后移动sizeof(int),即*(a+1)就是a[1]。
  2. &a是指向数组的指针,类型为int(*)[10]。a+1会向后移动sizeof(int) * 10。即数组尾元素之后的位置

3 static关键字有什么作用?

  1. 修饰局部变量
    (1)静态局部变量存储在静态存储区内。
    (2)静态局部变量仅在第一次调用时创建并初始化,后续调用到其定义代码时,不会再次定义或初始化;
    (3)静态局部变量的生命周期从其定义时开始,直到程序结束。
    (4)静态局部变量仅在其定义域中可见,在其定义域之外不可见。
  2. 修饰全局变量
    (1)静态全局变量存储在静态存储区内;
    (2)静态全局变量的生命周期从其定义位置开始,直到程序运行结束。
    (3)静态全局变量在其声明的文件内可见,在文件外不可见。
  3. 修饰函数
    (1)static修饰的函数仅在其定义的文件中可见,文件外不可见。由此可以避免函数命名冲突。
  4. 修饰成员变量
    (1)static修饰的成员变量只有一份拷贝,为该类的所有对象共享。
    (2)static修饰的成员变量无需实例化即可访问;
    (3)static修饰的成员变量在类外部初始化,且初始化时不加static。
  5. 修饰成员函数
    (1)static修饰的成员函数无需实例化也可调用;
    (2)static修饰的成员函数不接受this指针
    (3)static修饰的成员函数不能使用非static的成员变量,只能使用静态成员。

4 #define和const有什么区别?

  1. 编译器处理方式不同
    (1)#define在预处理阶段进行替换,不能调试。
    (2)const常量在编译阶段处理。
  2. 类型和安全检查不同
    (1)#define不做类型检查,仅是代码展开,可能产生边际效应等错误。
    (2)const常量具有类型,在编译阶段会进行类型检查。
  3. 存储方式不同
    (1)#define是单纯的替换,不分配内存,存储在程序的代码段中。
    (2)const常量会分配内存,但仅维持一份拷贝,存储在程序的数据段中。
  4. 定义域不同
    (1)#define不受定义域限制。
    (2)const常量仅在定义域内有效。

5 对于⼀个频繁使用的短小函数,应该使用什么来实现?有什么优缺点?

应使用inline内联函数来实现。

优点:

  • inline函数省略了函数调用的过程,效率相对更高;
  • inline函数会进行语法检查和类型检查,安全性比宏函数更好。

缺点:

  • inline函数在所有调用位置展开,代码膨胀;
  • 如果inline函数的执行时间比调用时间长很多,则省略函数调用带来的效率提升并不明显。
  • 如果inline函数修改,则所有使用此函数的源码文件都需要重新编译。
  • inline函数只是建议,编译器是否内联是不确定的。

6 什么是智能指针?智能指针有什么作用?分为哪几种?各自有什么样的特点?

智能指针是为了解决手动申请、释放动态内存容易导致内存泄露和空悬指针的问题而出现的。智能指针会自动管理动态内存,在析构时释放资源。

auto_ptr:

  • auto_ptr是C++98的概念,在C++11中已被淘汰;
  • auto_ptr本质上是独占的智能指针,但将其赋值给另一个智能指针是不会报错,此时继续使用前者可能导致内存崩溃。

unique_ptr:

  • unique_ptr是独占式的指针,同一时间只能有一个智能指针指向该对象。
  • unique_ptr不能拷贝构造和拷贝赋值,但可以移动构造和移动赋值。

shared_ptr:

  • shared_ptr是共享式的智能指针,允许多个智能指针同时指向同一对象。
  • shared_ptr有引用计数,用于记录当前有多少智能指针指向该对象。
    • 构造函数中,将引用计数初始化为1;
    • 拷贝构造函数中,将引用计数+1;
    • 赋值运算符中,将左侧对象的引用计数-1,右侧对象的引用计数+1;
    • 析构函数中,引用计数-1;
    • 在析构或赋值时,如果某个对象的引用计数减为0,则调用delete释放对象。
  • 成员函数:
    • use_count:返回引用计数的个数;
    • unique:返回是否独占
    • swap:交换两个shared_ptr对象
    • reset
    • get

weak_ptr:

  • weak_ptr是不影响所指对象生命周期的智能指针。weak_ptr是对对象的弱引用,可以绑定到shared_ptr,但weak_ptr的构造和析构不会改变引用计数;
  • weak_ptr解决shared_ptr相互引用时,两个指针的引用计数永远不会减为0,从而导致的死锁问题。
  • weak_ptr和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给weak_ptr,weak_ptr可以通过lock函数获得shared_ptr。
  • 不能通过weak_ptr直接访问对象的方法,要先转化为shared_ptr再访问。

7 shared_ptr是如何实现的?

  • 构造函数中,引用计数初始化为1;
  • 拷贝构造函数中,引用计数+1;
  • 赋值时,左侧对象引用计数-1,右侧对象引用计数+1
  • 析构函数中,引用计数-1。
  • 在赋值和析构函数中,如果引用计数降为0,调用delete释放对象。

8 右值引用有什么作用?

9 悬挂指针与野指针有什么区别?

悬挂指针:指针所指的对象已经释放,但指针仍指向这块已经被回收的内存。

野指针:未经初始化的指针。

10 静态链接和动态链接有什么区别?

静态链接在编译的链接阶段将执行代码拷贝到调用位置。

优点:

  • 程序独立运行,不依赖库文件;
  • 前期执行效率比动态链接略高。

缺点:

  • 程序体积较大。如有多个程序使用同一静态库,会有一定空间浪费;
  • 静态库更新后,相关可执行文件均需重新链接。

动态库不拷贝执行代码,而是在程序运行或加载时将一系列符号和参数传给操作系统,由操作系统将对应的动态库加载到内存中。需要调用相关代码时,再去共享内存中查找,从而实现动态链接。

优点:

  • 多个程序可以共用一个动态库,节省资源;
  • 动态库更新后,可执行文件不用重新链接;

缺点:

  • 程序依赖动态库,如操作系统中动态库缺失,则无法使用;
  • 由于是动态加载,前期执行效率会比静态库略慢。

11 变量的声明和定义有什么区别

(1)变量定义时分配内存,声明则不分配内存;
(2)变量定义仅有一处,但声明可以有多处;
(3)使用extern修饰的是变量声明,说明该变量将在本文件后续位置或其他文件中定义。

12 简述#ifdef、#else、#endif和#ifndef的作用

(1)使用条件编译将功能模块包含进去,可以快捷打开/关闭某个功能;
(2)可用于快速打开/关闭调试信息。
(3)不同硬件平台的差异处理。

13 写出int、bool、float、指针变量与“零值”比较的if语句

// int
if (i == 0)
if (i != 0)

// bool
if (b)
if (!b)

// 指针
if (p == nullptr)
if (p != nullptr)

// float
#define EPSINON 0.00001
if ((x >= -EPSINON) && (x <= EPSINON))

14 结构体可以直接赋值吗

结构体可以在定义时直接初始化,同一结构体的不同对象之间也可以相互赋值。但如果结构体内存在指针类型的变量,则在释放时需要注意是否还有其他对象使用这段内存。

15 sizeof和strlen的区别

(1)sizeof是操作符,strlen是库函数;
(2)sizeof的结果在编译阶段即可确定,strlen则在运行时确定;
(3)sizeof可以处理类型、变量、数组等,strlen仅能处理以’\0’结尾的字符数组;
(4)sizeof计算的是实际占用内存空间的大小,strlen计算的是字符个数。
(5)数组做sizeof的参数不退化,传递给strlen会退化为指针。

16 C语言的关键字static和C++的关键字static有什么区别

C语言的static关键字可以修饰局部变量、全局变量、函数。

C++的static关键字除了局部变量、全局变量、函数之外,还可以修饰成员变量和成员函数。

17 volatile有什么作用

volatile通知编译器不要优化该变量,每次使用变量时,都从内存重新读取,而不是从寄存器读取备份。

常见的应用场景:

  • 状态寄存器一类的并行设备硬件寄存器;
  • 中断服务子程序会访问到的非自动变量;
  • 多线程间被几个任务共享的变量。

18 一个参数可以既是const又是volatile吗

可以。const只是说明在此程序中该参数是只读的,并不是实际禁止这段内存的读写特性。它仍有可能在程序外部条件变化下改变。volatile通知编译器不要优化该变量,每次使用变量时,都从内存重新读取,而不是从寄存器读取备份。

19 全局变量和局部变量有什么区别?操作系统和编译器是怎么知道的?

区别:
(1)全局变量定义在所有函数之外,定义位置之后均可使用。生命周期从程序运行到结束。
(2)局部变量定义在代码块中,仅在该代码块中可见。生命周期从定义位置到代码块结束。

操作系统和编译器应是根据内存中存储位置判断的。全局变量位于全局数据区,在程序运行时被加载。局部变量位于栈区。

20 简述strcpy、sprintf与memcpy的区别

(1)功能区别:

  • strcpy用于两个字符串之间的拷贝;
  • sprintf用于将其他类型数据格式化为字符串;
  • memcpy是在两块内存之间拷贝。

(2)操作对象区别:

  • strcpy的两个操作对象均为字符串;
  • sprintf的源对象可以是多种类型,目标对象是字符串;
  • memcpy的两个操作对象均是内存地址

(3)效率区别:
memcpy效率最高,strcpy次之,sprintf效率最低。

21 请解析((void ()( ) )0)( )的含义

22 C语言的指针和引用和c++的有什么区别?

(1)C语言没有引用的概念。
(2)指针本身占用内存,引用则是其他对象的别名,不占用内存。
(3)sizeof作用于指针,结果为4。sizeof作用于引用,结果是其所指对象的大小。
(4)指针有顶层const和底层const,引用只有底层const。
(5)非顶层const的指针可以修改,引用则不能修改;
(6)指针可以二级,引用则只能有一级;
(7)通过指针操作所指对象需要先解引用,引用则可以直接操作。
(8)对指针执行加法,会造成所指内存地址偏移。对引用执行加法,会导致其所指对象的数值改变。
(9)如果返回动态内存分配的对象或内存,必须使用指针。引用可能导致内存泄露。

23 typedef和#define有什么区别

(1)typedef通常用于定义数据类型别名,以增强程序可读性。#define则常用于定义常量、宏函数等。
(2)typedef在编译阶段处理,#define则在预处理阶段替换。typedef会进行类型检查,#define没有类型检查;
(3)typedef有作用域限制,#define没有作用域限制,在其声明后的使用都是正确的。
(4)typedef和#define对指针的操作有很大区别。

24 指针常量与常量指针区别

指针常量是顶层const。指该指针本身是常量,不能修改其所指的地址,但可以通过该指针修改其所指内存中的数据。

常量指针是底层const。该指针所指的地址可以改变,但不能通过该指针修改其所指内存中的数据。

25 简述队列和栈的异同

队列和栈都是线性存储结构。区别在于队列是先进先出,栈是后进先出。

26 设置地址为0x67a9 的整型变量的值为0xaa66

int *p = (int *)0x67a9;
*p = 0xaa66;

在任何硬件平台上,地址长度和整型变量的长度都是相同的。因此,整型数据可以强制转换为地址使用。

27 C语言的结构体和C++的有什么区别

(1)C语言的结构体中不能定义成员函数;
(2)C语言的结构体中没有访问说明符,不存在权限的概念。
(3)C语言的结构体没有继承关系。

28 如何避免“野指针”

(1)定义指针时执行初始化。如不明确应指向哪个对象,则初始化为nullptr。
(2)指针所指的对象被delete释放后,应将指针赋值为nullptr。
(3)指针所指变量的作用域结束前,释放变量并将指针赋值为nullptr。

29 句柄和指针的区别和联系是什么?

Windows操作系统用句柄来表示系统资源,是unsigned int类型。指针则是指向内存地址。两者是不同的概念。

30 说一说extern“C”

extern "c"添加在头文件中,作用是使编译器按C语言方式来编译代码,正确实现C++语言对C语言的调用。

31 C++的顶层const和底层const ?

顶层const:对象本身是常量。

底层const:所指对象是常量。

以指针为例说明。

  • 顶层const:指针指向的地址是固定的,但该地址中的数据可以修改。
  • 底层const:指针指向的地址可以改变,但不能通过该指针来改变所指地址内保存的数据。

32 栈区和堆区的区别?栈区和堆栈的区别?

栈区由编译器分配、释放。主要用于存储局部变量、函数参数等。堆区由编程者手动申请、释放。主要用于动态内存操作。

栈区、堆区和堆栈是两个层面的概念。栈区、堆区指的是内存的分区,堆栈指的是一种数据结构。

标签:面试题,01,const,区别,C++,引用,ptr,指针
来源: https://blog.csdn.net/murongmochen/article/details/122568253

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有