【c++面试集】年度整理
- 电脑硬件
- 2025-08-06 17:42:03

系列文章目录
文章目录 系列文章目录前言一、C++基础(必备)三目运算符表达式原码、反码和补码常量定义变量定义变量持久性lambda 表达式默认捕获变量const、virtual、static和noexcept关键字的用法自增自减在while中使用模板使用类和结构体区别标准库strcpy使用sizeof 运算符计算字节数#include默认路径搜索容器vector运算符重载运算符类型转换 二、C++面向对象面向对象语言特性多态性初始化列表的初始化顺序派生类构造函数和析构函数的执行顺序类构造函数次数虚函数实现原理重载、重写和隐藏 三、C++内存管理指针数组和运算符优先级别: [] > * > ++二维指针使用堆与栈 四、C++11 及现代 C++特性智能指针和移动语义nullptr 和 NULL的区别 五、进程通信进程间通信协程和线程 六、算法链表插入 七、推荐书籍八、推荐网站
前言
每一年有的企业会对相关专业做一次语言考试,作为个人也应对自己的主要编程语言做一次年度考试。
一、C++基础(必备) 三目运算符表达式条件表达式 “a?b:c”,当a为真时,取b值,否则取c值。C/C++遵循的规则是“非零即为真”,所有不是零的数,都可以认为是“true”,而仅把零当做false,即“为真”即“不等于零”,“为假”即“等于零”,所以题目中w等价的表达式是w非零。
若有表达式“(w) ? (–x) : (++y)”,则其中与w等价的表达式是: w!=0
原码、反码和补码正数的原码、反码和补码都相同;负数原码和反码的相互转换的方式是符号位不变,数值位按位取反;负数原码和补码的相互转换的方式是符号位不变,数值位按位取反,末位再加1;0的补码表示只有一种。
下列关于原码、反码和补码的描述,正确的是: ABCD
A、负整数的符号位为1 B、0的补码是唯一的 C、正整数的原码、反码和补码都一样 D、十进制数-122的原码为11111010,反码为10000101,补码为10000110
常量定义下列哪些写法是对的,而且是常量? ABD
A、125 B、1.25E+20 C、‘AB’ D、-0.456
变量定义下列代码的main函数中哪个标志符是变量名?
class Base { public: Base() {} Base(int i) : counter(i) { } private: int counter = 0; }; int main() { Base a(); // 函数声明的优先级最高,所以标志符a是函数名 Base b(1); // 变量名 Base c = 1;// 变量名 Base d{};// 变量名 return 0; } 变量持久性全局变量持久性跟进程相同;静态全局变量改变的链接性,持久性跟进程相同;静态局部变量的作用域是局部的,但是持久性跟进程相同;静态成员变量的持久性跟进程相同。
以下哪种类型的变量的持久性跟进程是一样的? BCEF
A、非静态成员变量 B、静态全局变量 C、静态局部变量 D、非静态局部变量 E、静态成员变量 F、全局变量
lambda 表达式默认捕获变量lambda只能捕获非静态局部变量,不能捕获全局变量和静态局部变量;this是一种特殊的局部变量。
下面的代码,lambda表达式捕获了哪几个变量? BD
int g_counter = 0; class Base { public: void testLambda() { int index = 0; static int counter = 1; auto callback = [=]() // =代表可以捕获所有,但lambda只能捕获非静态局部变量,不能捕获全局变量和静态局部变量; this是一种特殊的局部变量 { }; } }; A、counter B、this C、g_counter D、index const、virtual、static和noexcept关键字的用法 const关键字可以用来修饰变量和函数virtual关键字只能用来修饰函数和类继承static关键字可以用来修饰变量和函数,用来定义静态成员变量和静态成员函数;还可以用来改变全局变量的链接行以及局部变量的持久性;也可以改变全局函数的链接性noexcept关键字用来表明该函数不会产生异常,允许编译器尽量优化异常相关的代码以下哪几个关键字即可用来修饰变量又可以用来修饰函数? AD
A、const B、virtual C、noexcept D、static
自增自减在while中使用 #include <iostream.h> void main() { int num=2,i=6; do { i--; num++; } while(--i); cout<<num<<endl; // do-while循环,前缀先使i减少1后判断是否为零,不为零时再次执行循环,为零退出循环。循环值执行3次就退出,所以结果为5。 } 模板使用模板是类型无关的,具有很高的可复用性;模板是平台无关的,可移植性;模板是编译时检查数据类型而不是运行时,保证了类型安全;模板可用来创建动态增长和减少的数据结构。
C++中使用模板类的原因,下列描述正确的是? ABD
A、可用于基本数据类型 B、可用来创建动态增长和减小的数据结构 C、它是类型相关的,因此具有很高的可复用性。 D、它是平台无关的,可移植性 E、它在运行时而不是编译时检查数据类型,保证了类型安全
类和结构体区别class 可以使用模板,而 struct 不能。
关于C++中类class和C语言中struct的区别描述,说法正确的是? ACD
A、class中的成员默认是private 属性的,struct的成员默认是public 属性的 B、class 和struct都可以使用模板类型 C、class有继承、多态的特性,struct没有 D、class可以定义成员函数,struct只能定义成员变量
标准库strcpy使用 // 请问运行Test 函数会有什么样的结果? void Test(void) { char *str = (char *) malloc(100); strcpy(str, “hello”); free(str); if(str != NULL) { strcpy(str, “world”); // world printf(str); } } sizeof 运算符计算字节数sizeof计算结构体字节数
// 假设sizeof(int)等于4,则sizeof(struct Derived)的值是什么? // 编译器默认会在结构体成员变量之间插入补齐字节,确保每一个成员变量都是自然对齐的。 struct Base { char a; // 偏移量为0, 0 + 1 = 1 int b; // 偏移量为4,4 +4 = 8 char c; // 偏移量为8, 8 + 1 = 9, 但要自然对齐规则的满足为int(4) 的整数倍,因此添加3个pad, 为8 + 1 + 3 = 12 }; // 12,结构体整体大小为最大字节数为int(4)的整数倍 // 如果子类中所有成员的自然对齐要求小于父类的话,则子类需要按照父类的自然要求进行对齐,也可以理解成嵌套结构体的字节数 // 嵌套结构体字节数需要将嵌套结构体展开计算偏移量(为接下来要放置变量的整数倍),而不是整个计算。 struct Derived : public Base { char d; };sizeof 计算数组的字节数
// 某32位系统下,C++程序,请计算sizeof 的值,按程序执行顺序,应该输出什么 // 数组名作函数的参数,主调函数和被调函数共用一段存储单元 void Foo ( char str[100] ) { printf("sizeof(str)=%d \n", sizeof(str) ); } void main() { char str[] = "www.ibegroup.com"; char *p1 = str ; int n = 10; void *p2 = malloc( 100 ); printf("sizeof(str)=%d \n", sizeof(str) ); // 17 printf("sizeof(p1)=%d \n", sizeof(p1) ); // 4 printf("sizeof(n)=%d \n", sizeof(n) ); // 4 printf("sizeof(p2)=%d \n", sizeof(p2) ); // 4 Foo(str); // 4 }sizeof 计算类的字节数
1.假设sizeof(long)等于4 2. 给定一个类C,该类不继承任何其他类 3. 该类的内存布局采用编译器默认逻辑 4. 该类中包含一个int类型非静态成员和两个char类型的非静态成员变量 则,sizeof(C)表达式可能的求值结果是多少? ABD A、16 // char int char 和考虑定义虚函数;如果该类定义了虚函数,则需要增加一个虚函数表指针成员变量,其大小为sizeof(long) B、8 // char char int ,不考虑虚函数 C、10 D、12 // char int char,不考虑虚函数 #include默认路径搜索#include 和 #include “filename.h” 有什么区别? D
A、对于#include ,编译器从用户的工作路径开始搜索filename.h;对于#include “filename.h” ,编译器从用户的工作路径开始搜索filename.h B、对于#include ,编译器从用户的工作路径开始搜索filename.h;对于#include “filename.h” ,编译器从标准库路径开始搜索filename.h C、对于#include ,编译器从标准库路径开始搜索filename.h;对于#include “filename.h” ,编译器从标准库路径开始搜索filename.h D、对于#include ,编译器从标准库路径开始搜索filename.h;对于#include “filename.h” ,编译器从用户的工作路径开始搜索filename.h
容器vector运算符重载vector::iterator重载了下面哪些运算符? ABD
A、++ B、== C、>> D、*(前置)
运算符类型转换C++运算法匿名转换向高类型转换。
已知:char a ; float b ; double c ; 则执行语句:c = a + b + c; 后变量c的类型为:double
以下两条输出语句,按照顺序,输出什么
float a = 1.0f; cout << (int)a << endl; cout << (int&)a << endl; cout << boolalpha << ( (int)a == (int&)a ) << endl; // false float b = 0.0f; cout << (int)b << endl; cout << (int&)b << endl; cout << boolalpha << ( (int)b == (int&)b ) << endl; // true 二、C++面向对象 面向对象语言特性下列对C++语言特点描述正确的选项是?ABD
A、可以担负起以模版为特征的泛型化编程 B、在C语言的基础上进行扩充和完善,使C++兼容了C语言的面向过程特点,又成为了一种面向对象的程序设计语言 C、可以使用抽象数据类型进行面向过程的编程 D、可以使用多继承、多态进行面向对象的编程
多态性关于C++的多态性,下列描述正确的是?ABCD
A、存在虚函数的类都有一个一维的虚函数表叫做虚表,类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是和对象对应的 B、在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数 C、多态用虚函数来实现,结合动态绑定 D、多态性是一个接口多种实现,是面向对象的核心,分为类的多态性和函数的多态性 E、用virtual关键字申明的函数叫做虚函数,虚函数不一定是类的成员函数
初始化列表的初始化顺序初始化列表的初始化顺序:为了避免两次构造,推荐使用类构造函数初始化列表。初始化列表不是按照列表的顺序进行的;是按照内存模型中的成员变量的顺序(也即类声明的定义顺序)进行的;为了避免出现依赖的问题,应当让参数列表和在类内的成员变量声明保持一致。
class A { public: A():n2(0), n1(n2+0){} void print() { cout << "n1: " << n1 << ", n2: " << n2 << endl; } private: int n1; int n2; }; int main(int, char**) { A a; // 初始化的顺序是由类内定义的顺序决定的,先初始化 n1,而 n1 由未被赋值的 n2 初始化 a.print(); // n1: -858993458, n2: 0 return 0; } 派生类构造函数和析构函数的执行顺序派生类构造函数必须对这三类成员进行初始化,其执行顺序:调用基类构造函数;调用子对象的构造函数;派生类的构造函数体。
析构函数在执行过程中也要对基类和成员对象进行操作,但它的执行过程与构造函数正好相反,即对派生类新增普通成员进行清理;调用成员对象析构函数,对派生类新增的成员对象进行清理;调用基类析构函数,对基类进行清理。
有程序如下: #include<iostream> using namespace std; class A { public: A() { cout << "A"; } }; class B { public:B() { cout << "B"; } }; class C : public A { B b; public: C() { cout << "C"; } }; int main() { C obj; // "ABC" return 0; } 类构造函数次数假定AB为一个类,则执行“AB a(2), b[3],*p[4];”语句时调用该类构造函数的次数为: 4 。
a(2)调用1次带参数的构造函数,b[3]调用3次无参数的构造函数,*p[4]指针没有给它分配空间,没有调用构造函数。所以共调用构造函数的次数为4
虚函数实现原理在下面的代码中,函数调用语句base->print();会产生什么行为?
#include <stdio.h> class Base { public: virtual void print() { printf("%d\n", counter++); } private: static int counter; }; // static int Base::counter = 0; int main() { Base* base = nullptr; // this 指针为空指针 base->print(); // 运行崩溃,虚函数使用虚函数表实现;带有虚函数的类都会有一个由编译器插入的成员变量:虚函数表指针 return 0; }给定下面的代码,使用main函数的中的局部变量b分别调用Func1、Func2、Func3和Func4,哪个函数调用会产生崩溃?
class Base { public: Base() : b(1) {} void Func1() { printf("Func1 b = %d\n", b); } // 崩溃,this指针为空指针,使用空指针访问成员变量会引发崩溃 virtual void Func2() { printf("Func2\n"); } // 崩溃,函数是虚函数,需要首先使用空指针获取虚函数表指针成员变量,引发崩溃 void Func3() { printf("Func3\n"); } // 不崩溃,this指针为空指针,但是,没有访问成员变量,不崩溃 static void Func4() { printf("Func4\n"); } // 不崩溃,函数是静态成员函数,函数内部不能使用this,不崩溃 private: int b; }; int main() { Base* b = nullptr; // this 指针为空指针 printf("done!\n"); return 0; } 重载、重写和隐藏 #include <stdio.h> 在下面的代码中,打印结果是什么? class Base { public: Base(int c1) { counter = c1; } virtual void printCounter() { printf("%d\n", counter++); } protected: int counter = 1; }; class Derived : public Base { public: Derived(int c1) : Base(c1) { } void printCounter() override // 子类继承父类并重写了父类的虚函数 { printf("%d\n", counter); } }; int main() { Derived d(2); // 使用子类实例可以初始化父类对象,并且默认采用拷贝构造 Derived* pd = &d; Base& rb = *pd; // 父类引用和指针都可以指向子类实例 rb.printCounter(); // 2 Base b = d; b.printCounter(); // 2 return 0; } 三、C++内存管理 指针数组和运算符优先级别: [] > * > ++指针数组:数组元素都是相同类型的指针,相同类型的指针是说指针所指向的对象类型是相同的。
运算符优先级别: [] > * > ++
int *p[5]; 定义了一个指针数组,在指针数组的定义中有两个运算符:*和[ ],运算符[ ]的优先级高于*,所以*p[5]等价于*(p[5]),p[5]表示一个数组,而*表示后面的对象为指针变量,合在一起*p[5]表示一个指针数组。该数组包含5个元素,每个元素都是指向int型的指针。
二维指针使用 执行以下程序段后,m的值为 ( )。 int a[2][3]={{1,2,3},{4,5,6}}; int m,*p=&a[0][0]; m=(*p)*(*(p+2))*(*(p+4)); // 1 * 3 * 5 = 15 堆与栈C++中什么数据分配在栈中? ACDE A、函数调用参数 B、静态局部变量 C、局部变量 D、函数返回值 E、函数返回地址
Heap与stack的差别描述正确的是? BCD
A、Heap空间有限,Stack是很大的自由存储区 B、C中的malloc函数分配的内存空间即在堆上,C++中对应的是new操作符。 C、程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行 D、Stack的空间由操作系统自动分配/释放,Heap上的空间手动分配/释放。
四、C++11 及现代 C++特性 智能指针和移动语义智能指针类std::unique_ptr支持移动构造和移动赋值,在变量定义时使用等号进行初始化会调用构造函数而不是赋值函数。
在下面的代码中,初始化abc2变量时调用的是什么函数?
std::unique_ptr<std::string> abc(new std::string("abc")); std::unique_ptr<std::string> abc2 = std::move(abc); // 移动构造 nullptr 和 NULL的区别在 C++ 中,NULL 的定义实际上是一个整数值 0,而不是一个真正的指针类型。
在函数重载和模板编程中这可能会导致一些问题和歧义。
为了解决这个问题,C++11 引入了一个新的关键字 nullptr,用于表示空指针。
nullptr 是一种特殊类型的字面值,类型为 std::nullptr_t,定义为: typedef decltype(nullptr) nullptr_t,可以隐式转换为任何指针类型。
与 NULL 不同,nullptr 是一个真正的指针类型,因此可以避免一些由于 NULL 是整数类型而引起的问题。
五、进程通信 进程间通信关于几种进程间通信方式描述,下列选项正确的是? ABCD
A、共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信 B、管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系 C、消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点 D、信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段
协程和线程关于协程描述,下列正确的是?ABCE
A、支持跨平台、跨体系架构、无需线程上下文切换的开销、无需原子操作锁定及同步的开销、方便切换控制流,简化编程模型 B、进行阻塞(Blocking)操作,如IO时,会阻塞掉整个程序,可以使用异步IO操作来解决 C、协程是协作式,线程是抢占式 D、协程没有自身的寄存器上下文和栈,使用系统的 E、协程是一种用户态的轻量级线程。
程序什么时候应该使用线程,什么时候单线程效率高,描述正确的是? CD
A、多CPU系统中,使用线程会降低CPU利用率 B、耗时的操作不应使用线程,会降低应用程序响应时间 C、并行操作时使用线程,如C/S架构的服务器端并发线程响应用户的请求 D、一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改,其他情况都使用单线程
同一进程下的线程可以共享以下? CD
A、thread ID B、register set C、stack D、data section
六、算法 链表插入在一个单链表结构中,指针p指向链表的倒数第二个结点,指针s指向新结点,则能将s所指的结点插入到链表末尾的语句组是? BCD
A、p=p->next; s->next=p; p->next=s B、p=(*p).next; (*s).next=(*p).next; (*p).next=s C、p=p->next; s->next=p->next; p->next=s D、s->next=NULL; p=p->next; p->next=s
七、推荐书籍学习新东西的时候,注重知识的体系性和框架的建立,然后集中时间,快速抓住领域的主线,突出重点去学习。对于细枝末节的零散内容,可以留到实践的时候,用到了再去查看。
书名推荐情况预估时间《C++ Primer》推荐全看,按照目录索引查漏补缺2个月《Effective C++》推荐全看,掌握 C++ 编码规范3周《深度探索 C++ 对象模型》推荐前3章,掌握内存模型整体概念2周《STL 源码剖析》推荐掌握vector, map, quene STL 源码和底层机制3周 八、推荐网站C++ 日常开发一定要记得以下几个网站,可以随时查阅一些语法的用法和标准库:
https://en.cppreference.com/w/https://cplusplus.comhttps://isocpp.org【c++面试集】年度整理由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【c++面试集】年度整理”
上一篇
Flutter基础