【C++】面试题整理(未完待续)

news/2025/1/19 14:20:35/

【C++】面试题整理

文章目录

    • 一、概述
    • 二、C++基础
      • 2.1 - 指针在 32 位和 64 位系统中的长度
      • 2.2 - 数组和指针
      • 2.3 - 结构体对齐补齐
      • 2.4 - 头文件包含
      • 2.5 - 堆和栈的区别
      • 2.6 - 宏函数比较两个数值的大小
      • 2.7 - 冒泡排序
      • 2.8 - 菱形继承的内存布局
      • 2.9 - 继承重写
      • 2.10 - 如何禁止类在栈上分配内存
    • 三、智能指针
      • 3.1 - 智能指针是线程安全的吗?
      • 3.2 - 线程安全的几种方法
    • 四、 STL
      • 4.1 - map 删除
    • 五、参考

一、概述

最近面试,感觉有些比较基础的好久不用就有些生疏了,整理一下。

【备注】:题目的答案是个人整理的不能保证是标准答案。

二、C++基础

2.1 - 指针在 32 位和 64 位系统中的长度

4 字节和 8 字节

32/8 = 4
64/8 = 8

2.2 - 数组和指针

以下代码在 32 位和 64 位系统中分别打印什么?

char a[] = "123456789";
const char* b = "123456789";
std::cout << sizeof(a) << std::endl;
std::cout << sizeof(b) << std::endl;
  • 32位打印: 10 和 4
  • 64位打印: 10 和 8

指针已经在第一题中说过了,就不重复了。char 数组的大小需要加上最后的 \0

2.3 - 结构体对齐补齐

在 32 位和 64 位系统中分别是多少

struct M
{int a;double b;
};printf("%d", sizeof(struct M));

答案: 均为16,这里是结构体的对齐补齐,与系统位数无关。

2.4 - 头文件包含

两种包含头文件的区别

#include <stdio.h>
#include "stdio.h"
  • 尖括号,编译器会从系统目录中查找;
  • 双引号,编译器会首先从当前项目目录查找,找不到再去系统目录中查找。

虽然#include"“的查找范围更广,但是这并不意味着,不论是系统头文件,还是自定义头文件,一律用#include”“包含。因为#include”"的查找顺序存在先后关系,如果项目当前目录或者引用目录下存在和系统目录下重名的头文件,那么编译器在当前目录或者引用目录查找成功后,将不会继续查找,所以存在头文件覆盖的问题。另外,对于系统头文件,用#include<>包含,查找时一步到位,程序编译时的效率也会相对更高。

2.5 - 堆和栈的区别

  • 堆(heap): 向上增长内存,存储动态分配的内存,需要程序员自己管理,分配和释放。
  • 栈(stack): 向下增长内存,存储静态分配的内存,系统会自动释放。

2.6 - 宏函数比较两个数值的大小

要求不使用大于、小于和if

#define MAX(a,b) (int)((a)/(b)) == 0 ? (a) : (b);

定义宏函数需要注意,入参需要使用小括号括起来,避免传入算式导致预期外的计算

MAX(4-1,5); 
// 不加小括号 4 - 1/5 = 3 返回3 值错误。
// 加小括号 (4-1)/(5) = 0, 返回值为 5。

2.7 - 冒泡排序

void bubbleSort(int arr*, int n)
{for (int i = 0; i < n - 1; ++i){for (int j = 0; j < n - i - 1; ++j){if (arr[j] > arr[j+1]){int tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = arr[j];}}}
}

如果我是面试官,我会在这里考一个打印 arr 的 sizeof ,因为 数组在传参时会退化为指针。

2.8 - 菱形继承的内存布局

class A
{
public:int a;
};class B : public A
{
public:int b;
};class C : public A
{
public:int c;
};class D : public B, public C
{
public:int d;
};

可以看到 A 中的内容被重复记录了两次

若改为虚继承,虚继承是为了解决冗余和二义性

class B : virtual public A {/*...*/};
class C : virtual public A {/*...*/};

在这里插入图片描述
则会出现一个虚基表指针 vbptr (virtual base pointer) 记录偏移

VS Developer Command Prompt 查看内存布局方法
cl /d1 reportSingleClassLayoutD filename.cpp

2.9 - 继承重写

实现一个 Shape 类,定义纯虚函数 area,定义 Rectangle 和 Circle 类继承 Shape 类,在main函数中打印面积。

class Shape
{
public:virtual double area() = 0;
};class Rectangle : public Shape
{
public: Rectangle(double width, double length):m_width(width), m_length(length) {}virtual double area() override{return m_width*m_length;}
private:double m_width {0.0};double m_length {0.0};	
};
#define PI 3.1415926
class Circle  : public Shape
{
public:Circle(double radius): m_radius(radius){}virtual double area() override{return PI * m_radius * m_radius}
private:double m_radius{0.0};	
};

调用

#include <iostream>
int main(int argc, char* argv[])
{Rectangle rect(3.0, 4.0);Circle c(2.0);std::cout << rect.area() << std::endl;std::cout << c.area() << std::endl;
}

2.10 - 如何禁止类在栈上分配内存

其实只要禁用 析构就可以在编译时报错,但是为了方便继承和使用

class A 
{
public:static A* Create(){ return new A();}void Destroy() { delete this;} // 不能为 static,因为静态函数中无 this 指针
protected:~A() {};A() {};A(const A& rhs) {/*...*/};A(const A&& rhs) {/*...*/};const A& operator=(const A& rhs) {/*...*/};const A& operator=(const A&& rhs) {/*...*/};
};

三、智能指针

3.1 - 智能指针是线程安全的吗?

不是,虽然引用计数是原子操作,但还有其他的操作

3.2 - 线程安全的几种方法

  • 加锁
  • 原子变量 std::atomic

四、 STL

4.1 - map 删除

改错。

using std::map;
using std::string;
int main(int argc, char* argv[])
{map<string, string> mapData;mapData["a"] = "aaa"; mapData["b"] = "bbb"; mapData["c"] = "ccc"; for (map<string, string>::iterator i=mapData.begin(); i!=mapData.end(); i++){if (i->first == "b"){mapData.erase(i);}}return 0;
}

错误是容器删除元素会有迭代器失效,网上给的改错方式是,将for循环 i++ 删除 加到函数中

for (map<string, string>::iterator i=mapData.begin(); i!=mapData.end(); /*i++*/)
{if (i->first == "b"){mapData.erase(i++);}else{i++;}
}

个人感觉这样也可以

for (map<string, string>::iterator i=mapData.begin(); i!=mapData.end();++i)
{if (i->first == "b"){i = mapData.erase(i);--i;}  
}

五、参考

  • https://blog.csdn.net/rammuschow/article/details/107947302 include
  • https://en.cppreference.com/w/cpp/container/map/erase std::map erase 函数
  • https://blog.csdn.net/AgoniAngel/article/details/105893798 菱形继承内存分布

http://www.ppmy.cn/news/1564432.html

相关文章

openharmony应用开发快速入门

开发准备 本文档适用于OpenHarmony应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用&#xff08;如下图所示&#xff09;&#xff0c;快速了解工程目录的主要文件&#xff0c;熟悉OpenHarmony应用开发流程。 在开始之前&#xff0c;您需要了解有关OpenHarmon…

运行fastGPT 第四步 配置ONE API 添加模型

上次已经装好了所有的依赖和程序。 下面在网页中配置One API &#xff0c;这个是大模型的接口。配置好了之后&#xff0c;就可以配置fastGPT了。 打开 OneAPI 页面 添加模型 这里要添加具体的付费模型的API接口填进来。 可以通过ip:3001访问OneAPI后台&#xff0c;**默认账号…

CISSP一次通过我的经验分享

2024年3月15日&#xff0c;消费者权益保护日这天&#xff0c;爆出了很多日常外卖的料&#xff0c;朋友圈里都在说以后奶茶不能喝了&#xff0c;炸串不能吃了…….而我却没有关注这些&#xff0c;因为这一天是我CISSP考试的日子&#xff01; 我平时生活工作在江苏&#xff0c;因…

CVPR 2024 人体姿态估计总汇(3D人体、手语翻译和人体网格恢复/重建等)

1、Human Pose Estimation(人体姿态估计) CLOAF: CoLlisiOn-Aware Human FlowMeta-Point Learning and Refining for Category-Agnostic Pose EstimationSurMo: Surface-based 4D Motion Modeling for Dynamic Human Rendering ⭐codeGALA: Generating Animatable Layered Ass…

图像分类、目标定位与目标检测的区别详解:定义、工作原理、应用场景

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

【前端动效】HTML + CSS 实现打字机效果

目录 1. 效果展示 2. 思路分析 2.1 难点 2.2 实现思路 3. 代码实现 3.1 html部分 3.2 css部分 3.3 完整代码 4. 总结 1. 效果展示 如图所示&#xff0c;这次带来的是一个有趣的“擦除”效果&#xff0c;也可以叫做打字机效果&#xff0c;其中一段文本从左到右逐渐从…

图论1-问题 C: 算法7-6:图的遍历——广度优先搜索

题目描述 广度优先搜索遍历类似于树的按层次遍历的过程。其过程为&#xff1a;假设从图中的某顶点v出发&#xff0c;在访问了v之后依次访问v的各个未曾被访问过的邻接点&#xff0c;然后分别从这些邻接点出发依次访问它们的邻接点&#xff0c;并使“先被访问的顶点的邻接点”先…

【Linux】线程与同步互斥相关知识详细梳理

目录 1. 线程概念 2. 线程优势 3. 线程劣势 4. 线程控制 4.1 POSIX线程库 4.2 线程操作 5. 线程互斥 5.1 互斥相关概念 5.2 互斥量mutex 5.3 互斥量实现原理 6. 线程同步 6.1 同步概念与竞态条件 6.2 条件变量 6.3 条件变量使用规范及细节 1. 线程概念 什么是…