C++面试题和笔试题(一)

news/2024/4/24 17:20:40/文章来源:https://blog.csdn.net/IDdaxia/article/details/136573161

今天面试了一家100人以上的小公司,做QT上位机开发,个人感觉凉凉。以下是笔试题和我能回忆起的面试题

目录

一、笔试题

1. 什么是C++中的指针

官方解释:

 自己的理解:

2.什么是引用,它与指针有什么不同

官方解释:

自己的理解:

3.什么是多态?

4.什么是异常处理?如何在C++中实现?

5.请解释C++的const关键字,它在哪些情况下使用

5. 类成员

6.请解释C++中的static关键字,它在哪些情况下使用

1. 静态局部变量

2. 静态全局变量 

3. 静态类成员

4. 静态函数

7.请解释C++中的sizeof运算符,它返回什么?


一、笔试题

1. 什么是C++中的指针

官方解释:

C++中的指针是一个变量,其值为另一个变量的地址,即内存位置的地址。指针变量简称指针,它专用于存放变量在内存中的起始地址。指针是C/C++中的精髓所在,其特殊性在于它存放的是内存地址。 

在C++中,每定义一个变量,系统就会给变量分配一块内存,且内存是有地址的。指针变量通过存储这些地址,使得我们可以间接地访问和操作这些内存中的数据。因此,指针是实现动态内存分配、函数调用、数据结构等高级功能的重要工具。

声明指针的语法:数据类型 *变量名。例如,int *p; 就声明了一个指向整数的指针p。

 自己的理解:

 你有一个好朋友住在你家附近。你知道他家的地址,所以你可以根据这个地址找到他家,然后和他一起玩。

在这个例子里,地址就像是C++中的指针,而你的朋友家则是那个地址所指向的变量或者数据。

2.什么是引用,它与指针有什么不同

官方解释

 引用是C++中的一个概念,它是变量的一个别名,与原来的变量实质上指向同一块内存地址。当我们给一个变量起一个引用时,我们可以使用这个引用来代替原来的变量名,对引用的操作就是对原变量的操作。例如,如果我们有int a = 5;,然后定义int& ref = a;,那么ref就是a的一个引用,它们实际上都是指向同一个内存地址的。

自己的理解:

引用:你有一个很喜欢的玩具熊,你给这个玩具熊起了一个特别的名字,叫做“熊熊”。这个名字就是玩具熊的一个引用,每次你叫“熊熊”的时候,其实就是在说那个玩具熊。

指针:指针就像是一个小纸条,上面写着你朋友的家的地址。有了这个小纸条,你就可以找到你朋友的家,和他一起玩。

引用指针
定义与性质引用则是变量的别名,它和原变量实际上是同一个变量。指针是一个变量,它存储的是另一个变量的地址
存储空间引用则不占用额外的存储空间,它只是原变量的一个别名。指针有自己的存储空间,它的大小通常是固定的
初始化引用必须在定义时初始化,且一旦初始化后就不能再绑定到另一个变量上指针可以不初始化
可变性而引用的值(即它所代表的变量)在初始化后则不能改变。指针的值(即它所指向的地址)可以在初始化后改变,使其指向另一个对象
空值不能为空
多级引用与指针引用只能是一级可以有多级指针(例如int** p;
安全性好(因为引用在初始化后不能改变所指向的对象,这减少了出错的可能性。)
内存管理内存泄漏返回动态内存分配的对象或内存,必须使用指针

3.什么是多态?

简单来说,就是“一个接口,多种方法”。多态的实现方式主要依赖于继承和虚函数。

举几个代码例子

1).运行时多态(通过虚函数)

#include <iostream>  
#include <string>  // 基类 Animal  
class Animal {  
public:  virtual void speak() const {  std::cout << "The animal speaks." << std::endl;  }  virtual ~Animal() {} // 虚析构函数确保正确释放派生类资源  
};  // 派生类 Dog  
class Dog : public Animal {  
public:  void speak() const override {  std::cout << "The dog barks." << std::endl;  }  
};  // 派生类 Cat  
class Cat : public Animal {  
public:  void speak() const override {  std::cout << "The cat meows." << std::endl;  }  
};  // 使用多态的函数  
void letAnimalSpeak(const Animal& animal) {  animal.speak(); // 在运行时确定调用哪个 speak()  
}  int main() {  Dog dog;  Cat cat;  Animal* animalPtr;  animalPtr = &dog;  letAnimalSpeak(*animalPtr); // 输出: The dog barks.  animalPtr = &cat;  letAnimalSpeak(*animalPtr); // 输出: The cat meows.  return 0;  
}

在上面的例子中,Animal 类有一个虚函数 speak()Dog 和 Cat 类分别重写了这个函数。在 letAnimalSpeak 函数中,我们传入了一个 Animal 类型的引用,但实际上可以传入任何 Animal 的派生类对象。在运行时,程序会根据实际对象的类型调用相应的 speak() 函数。 

2).编译时多态(通过函数重载)

#include <iostream>  // 函数重载示例  
void print(int value) {  std::cout << "Integer: " << value << std::endl;  
}  void print(double value) {  std::cout << "Double: " << value << std::endl;  
}  void print(const std::string& text) {  std::cout << "String: " << text << std::endl;  
}  int main() {  print(42); // 输出: Integer: 42  print(3.14); // 输出: Double: 3.14  print("Hello, World!"); // 输出: String: Hello, World!  return 0;  
}

在这个例子中,我们重载了 print 函数,使其可以接受 intdouble 和 std::string 类型的参数。编译器根据传递给 print 函数的参数类型在编译时决定调用哪个版本的函数。这就是编译时多态的一个例子。

4.什么是异常处理?如何在C++中实现?

异常处理:是我们在生活中遇到问题时,找到合适的方法来解决它。在C++编程中,异常处理可以帮助我们找到并修复代码中的错误。

在C++中,这个过程可以这样实现:

1). throw:相当于你发现锅里的油着火了,你决定要采取行动,于是你“抛出”了一个问题,即火需要被扑灭

if (oil_is_on_fire) {  throw "Fire!"; // 抛出异常,表示发生了火灾  
}

2).try:你在厨房里做饭的时候(try块里的代码),一直在注意火的情况

try {  // 在这里做饭,可能会遇到油着火的情况  
}

 3).catch:当你发现火情(捕获到异常)时,你立即采取行动(执行catch块里的代码)来灭火。

catch (const char* message) {  // 灭火操作,比如用锅盖盖住锅  std::cout << "Caught an exception: " << message << ". Using the lid to put out the fire." << std::endl;  
}
catch (...) {  // 对于未知或无法处理的异常,我们可以做进一步的处理,比如发出警报  std::cout << "Unknown exception caught! Calling the firefighters!" << std::endl;  
}

5.请解释C++的const关键字,它在哪些情况下使用

在C++中,const关键字用于声明一个常量,即一个值在程序执行期间不能被修改的对象。

  • 保护数据不被意外修改:当你有一个不应该在程序执行期间改变的值时,使用const可以确保这个值不会被意外修改。
  • 提高代码可读性const变量提供了关于其用途的额外信息,使得代码更易读。
  • 优化:编译器可能会对const变量进行额外的优化,因为它们不会在运行时改变。
  • 作为函数参数和返回值的保证const可以用于函数参数和返回值,以表明参数或返回值在函数内部不会被修改。

下面是一些使用const的常见情况:

1. 声明常量值 

const int MAX_SIZE = 100;

2. 指针和const 

指向常量的指针:该指针不能用来修改它所指向的值。

const int* ptr = &some_integer; // ptr指向一个常量,不能通过ptr修改some_integer的值

常量指针:该指针自身不能被修改(即不能指向其他地址),但它所指向的值可以被修改(如果它不是指向一个常量的话)。

int value = 10;  
int* const ptr = &value; // ptr是一个常量指针,不能改变ptr指向的地址,但可以修改value的值

指向常量的常量指针:该指针自身不能被修改,同时它也不能用来修改它所指向的值。

const int value = 10;  
const int* const ptr = &value; // ptr是常量,value也是常量,两者都不能通过ptr被修改

3. 函数参数 

void func(const int& param) {  // 在func内部,param不能被修改  
}

4. 函数返回值 

const int* getPointer() {  static int value = 42;  return &value;  
}  
// 调用者不能通过返回的指针修改value的值

5. 类成员

class MyClass {  
public:  const int constantMember;  MyClass(int value) : constantMember(value) {}  
};  
// MyClass的实例一旦初始化后,constantMember的值就不能再被修改

 6. 类成员函数

class MyClass {  
public:  int getValue() const {  // 这个函数不会修改类的任何成员变量  return someMember;  }  
private:  int someMember;  
};  
// const成员函数保证不会修改类的状态

 7. 在数组中使用

const int arraySize = 5;  
int const arr[arraySize]; // 或者 int arr[arraySize] const;  
// arr的内容在初始化后不能被修改

6.请解释C++中的static关键字,它在哪些情况下使用

 在C++中,static是一个多功能的关键字,它可以用于多种上下文,包括变量、函数、类成员等。

以下是static关键字的主要用途和它们的使用场景:

1. 静态局部变量

当在函数内部声明一个静态局部变量时,这个变量只在程序执行到该变量的声明代码时初始化一次,并且在程序的整个生命周期内保持其值。即使函数返回后,静态局部变量的值也不会丢失。

自己的理解:想象你在家里有一个存钱罐,每次你得到零花钱,你都会放进这个存钱罐里。这个存钱罐就像是一个静态局部变量,因为它只在家里(函数内部)存在,并且每次你往存钱罐里放钱(函数调用),里面的钱(变量的值)都会累积起来,不会消失。即使你离开房间去做其他事情(函数返回),存钱罐里的钱还是会在那里

使用场景:当你想在函数调用之间保持某些状态或数据时,可以使用静态局部变量。

void addMoneyToPiggyBank() {  static int moneyInPiggyBank = 0; // 静态局部变量,初始化为0  int moneyToAdd = 5; // 假设每次添加5块钱  moneyInPiggyBank += moneyToAdd; // 往存钱罐里加钱  std::cout << "存钱罐里现在有 " << moneyInPiggyBank << " 块钱。\n";  
}

2. 静态全局变量 

静态全局变量只在其定义的文件中可见,而在其他文件中不可见。这提供了封装性,允许程序员隐藏不应在其他文件中使用的变量。

自己的理解:静态全局变量就像是你家里的一个秘密宝藏,只有你和你的家人知道它的存在。其他来你家做客的小朋友是看不到这个宝藏的。在C++中,如果一个全局变量被声明为static,那么它就只能在其所在的源文件中被访问,其他文件是看不到的。

使用场景:当你想限制全局变量的作用域到单个源文件时。

// 在你的房间的文件(file1.h)里  
static int secretTreasure = 10; // 静态全局变量,只有这个文件能看到  //另外一个文件(file1.cpp) 
void showTreasure() {  std::cout << "秘密宝藏里有 " << secretTreasure << " 颗糖果!\n";  
}

其他小朋友的文件(file2.cpp)里是不能访问secretTreasure的。

3. 静态类成员

静态类成员是类的所有对象共享的成员。它们不属于类的任何特定对象实例。静态成员变量必须在类外部定义和初始化。

自己的理解:静态类成员就像是全班同学共享的一个东西,比如班级的图书角。每个同学都可以从图书角借书,也可以放回书。图书角里的书不属于任何一个同学,而是属于整个班级。

使用场景:当你想存储与类本身相关而不是与类的任何特定对象实例相关的信息时。

class Classroom {  
public:  static int booksInLibrary; // 静态类成员,表示图书角里的书的数量  // ... 其他成员 ...  
};  // 在类外部定义和初始化静态成员变量  
int Classroom::booksInLibrary = 50; // 图书角初始有50本书

每个同学都可以改变booksInLibrary的值,来表示借书或还书的行为。

4. 静态函数

在函数外部(通常在命名空间或全局范围内),static用于声明函数的作用域为文件内部。这与静态全局变量的效果相似,它使得函数只在其定义的文件中可见。

自己的理解:你有一个秘密的食谱,只有你和你的家人知道怎么做。这个食谱就像static函数一样,只有在其定义的文件中才能使用。

使用场景

  • 当你需要保持某个变量的值在函数调用之间时,可以使用静态局部变量。
  • 当你需要在多个文件中共享某个变量,但又不想让它被其他所有文件访问时,可以使用静态全局变量。
  • 当你需要在不创建类实例的情况下访问某个变量或函数时,可以使用静态类成员。
  • 当你想要限制函数或变量的可见性,使它们仅在其定义的文件中可见时,可以使用静态函数或静态全局变量。
// file1.cpp  
static void myFunction() { // 静态函数  // ...  
}  // file2.cpp  
extern void myFunction(); // 错误!file2中不能访问file1中的静态函数

7.请解释C++中的sizeof运算符,它返回什么?

在 C++ 中,sizeof 是一个运算符,用于获取一个对象或类型的字节大小。它可以用于获取各种数据类型的大小,包括内置类型、类、结构体等。

自己的理解sizeof是一个运算符,用于获取一个对象或类型的字节大小。就像你在生活中会问“这个苹果有多大?”来了解苹果的大小一样,sizeof可以帮你了解一个对象或类型在计算机内存中占用了多少空间。

使用场景:

1.用于数据类型:你可以直接使用sizeof运算符获取基本数据类型(如intchardouble等)或复合数据类型(如数组、结构体、类等)的大小。例如:

std::cout << sizeof(int) << std::endl;  // 输出int类型在内存中的大小(以字节为单位)

2.用于变量:你也可以对变量使用sizeof运算符,这将返回该变量类型的大小,而不是变量本身所占用的内存空间大小。例如:

int x;  
std::cout << sizeof(x) << std::endl;  // 输出int类型在内存中的大小(以字节为单位)

3.用于数组:当用于数组时,sizeof返回的是整个数组所占用的内存空间大小,而不是数组中单个元素的大小。例如:

int arr[10];  
std::cout << sizeof(arr) << std::endl;  // 输出10个int类型在内存中的总大小(以字节为单位)

4.用于指针:当用于指针时,sizeof返回的是指针本身的大小,而不是指针所指向的内存空间大小。例如:

int *ptr;  
std::cout << sizeof(ptr) << std::endl;  // 输出指针类型在内存中的大小(以字节为单位)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_999229.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AI视野·今日Robot 机器人论文速览 第八十四期】Thu, 7 Mar 2024

AI视野今日CS.Robotics 机器人学论文速览 Thu, 7 Mar 2024 Totally 23 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers 3D Diffusion Policy Authors Yanjie Ze, Gu Zhang, Kangning Zhang, Chenyuan Hu, Muhan Wang, Huazhe Xu模仿学习提供了一种教…

js【详解】Promise

为什么需要使用 Promise &#xff1f; 传统回调函数的代码层层嵌套&#xff0c;形成回调地狱&#xff0c;难以阅读和维护&#xff0c;为了解决回调地狱的问题&#xff0c;诞生了 Promise 什么是 Promise &#xff1f; Promise 是一种异步编程的解决方案&#xff0c;本身是一个构…

防御保护--IPSEC VPPN实验

实验拓扑图 实验背景&#xff1a;FW1和FW2是双机热备的状态。 实验要求&#xff1a;在FW5和FW3之间建立一条IPSEC通道&#xff0c;保证10.0.2.0/24网段可以正常访问到192.168.1.0/24 IPSEC VPPN实验配置&#xff08;由于是双机热备状态&#xff0c;所以FW1和FW2只需要配置FW1…

解决方案TypeError: string indices must be integers

文章目录 一、现象&#xff1a;二、解决方案 一、现象&#xff1a; PyTorch深度学习框架&#xff0c;运行bert-mini&#xff0c;本地环境是torch1.4-gpu&#xff0c;发现报错显示&#xff1a;TypeError: string indices must be integers 后面报字符问题&#xff0c;百度过找…

阿里云服务器安装EMQX避坑指南

首先我们在EMQX官网按照教程安装了EMQX&#xff0c;博主采用的是Ubantu20.04 然后用netstat -lntu指令检测emqx是否启动 从上面这张图片可以看到我们的端口已经在本地运行了&#xff0c;18083是后台管理系统的端口。随后我们在阿里云服务器配置安全组规则。 但是即便做到这样仍…

数据结构之栈详解(C语言手撕)

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

如何保证消息不丢之MQ重试机制消息队列

1. 简介 死信队列&#xff0c;简称&#xff1a;DLX&#xff0c;Dead Letter Exchange&#xff08;死信交换机&#xff09;&#xff0c;当消息成为Dead message后&#xff0c;可以被重新发送到另外一个交换机&#xff0c;这个交换机就是DLX 那么什么情况下会成为Dead message&a…

智慧城市如何助力疫情防控:科技赋能城市安全

目录 一、引言 二、智慧城市与疫情防控的紧密结合 三、智慧城市在疫情防控中的具体应用 1、智能监测与预警系统 2、智慧医疗与健康管理 3、智能交通与物流管理 4、智慧社区与基层防控 四、科技赋能城市安全的未来展望 五、结论 一、引言 近年来&#xff0c;全球范围内…

鼠标右键没有git bash here,右键添加git bash here并增加图标

突然发现自己鼠标右键没有git bash here&#xff0c;或者安装之后就没有git bash here。后面那种情况多半是没有默认装在C盘。我们装在其他盘的时候就需要自己去配置。git gui目前用不上&#xff0c;这里只讲git bash here。网上一堆教程&#xff0c;说法不同大多不能用要么就很…

Docker部署SimpleMindMap结合内网穿透实现公网访问本地思维导图

文章目录 1. Docker一键部署思维导图2. 本地访问测试3. Linux安装Cpolar4. 配置公网地址5. 远程访问思维导图6. 固定Cpolar公网地址7. 固定地址访问 SimpleMindMap 是一个可私有部署的web思维导图工具。它提供了丰富的功能和特性&#xff0c;包含插件化架构、多种结构类型&…

1-Git-基础

版本控制 为什么要进行版本控制&#xff1f; **个人角度&#xff1a;**代码的修改繁杂&#xff0c;如果一点点修改代码&#xff0c;不利于开发。进行版本控制&#xff0c;可以在特定历史状态下进行修改。即可以进行回退和撤销操作 **团队角度&#xff1a;**每个人负责各自的…

垃圾收集器底层算法

垃圾收集器底层算法 三色标记 在并发标记的过程中&#xff0c;因为标记期间应用线程还在继续跑&#xff0c;对象间的引用可能发生变化&#xff0c;多标和漏标的情况就有可能发生&#xff0c;这里我们引入“三色标记”来给大家解释下把Gcroots可达性分析遍历对象过程中遇到对象…

灯塔:CSS笔记(2)

一 选择器进阶 后代选择器&#xff1a;空格 作用&#xff1a;根据HTML标签的嵌套关系&#xff0c;&#xff0c;选择父元素 后代中满足条件的元素 选择器语法&#xff1a;选择器1 选择器2{ css } 结果&#xff1a; *在选择器1所找到标签的后代&#xff08;儿子 孙子 重孙子…

opencv dnn模块 示例(24) 目标检测 object_detection 之 yolov8-pose 和 yolov8-obb

前面博文【opencv dnn模块 示例(23) 目标检测 object_detection 之 yolov8】 已经已经详细介绍了yolov8网络和测试。本文继续说明使用yolov8 进行 人体姿态估计 pose 和 旋转目标检测 OBB 。 文章目录 1、Yolov8-pose 简单使用2、Yolov8-OBB2.1、python 命令行测试2.2、opencv…

iOS-系统弹窗调用

代码&#xff1a; UIAlertController *alertViewController [UIAlertController alertControllerWithTitle:"请选择方式" message:nil preferredStyle:UIAlertControllerStyleActionSheet];// style 为 sheet UIAlertAction *cancle [UIAlertAction actionWithTit…

Unity性能优化篇(七) UI优化注意事项以及使用Sprite Atlas打包精灵图集

UI优化注意事项 1.尽量避免使用IMGUI(OnGUI)来做游戏时的UI&#xff0c;因为IMGUI的开销比较大。 2.如果一个UGUI的控件不需要进行射线检测&#xff0c;则可以取消勾选Raycast Target 3.尽量避免使用完全透明的图片和UI控件。因为即使完全透明&#xff0c;我们看不见它&#xf…

C#,老鼠迷宫问题的回溯法求解(Rat in a Maze)算法与源代码

1 老鼠迷宫问题 迷宫中的老鼠&#xff0c;作为另一个可以使用回溯解决的示例问题。 迷宫以块的NN二进制矩阵给出&#xff0c;其中源块是最左上方的块&#xff0c;即迷宫[0][0]&#xff0c;目标块是最右下方的块&#xff0c;即迷宫[N-1][N-1]。老鼠从源头开始&#xff0c;必须…

Docker安装主从数据库

我自己的主数据库名字 user_muster 密码是123456 从数据库 就是slave1 名字是root 密码是123456 首先开启docker后直接执行命令 docker run -d \ -p 3307:3306 \ -v /xk857/mysql/master/conf:/etc/mysql/conf.d \ -v /xk857/mysql/master/data:/var/lib/mysql \ -e MYSQL_R…

JavaWeb笔记 --- 一JDBC

一、JDBC JDBC就是Java操作关系型数据库的一种API DriverManager 注册驱动可以不写 Class.forName("com.mysql.jdbc.Driver"); Connection Statement ResultSet PrepareStatement 密码输入一个SQL脚本&#xff0c;直接登录 预编译开启在url中 数据库连接池

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:ImageAnimator)

提供帧动画组件来实现逐帧播放图片的能力&#xff0c;可以配置需要播放的图片列表&#xff0c;每张图片可以配置时长。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 ImageAni…