C/C++面试知识点

本文详述了C/C++面试中的常见问题,涵盖了C/C++的基础部分,包括静态全局变量的作用域、C与C++的区别、内存分配、引用与指针的区别、new/delete与malloc/free的使用等。还探讨了C++特性,如面向对象的三大特征、虚函数表、析构函数和虚函数的作用,以及静态成员与模板的区别。此外,还涉及了程序调试、类型安全、内联函数与宏的区别等知识点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C/C++面试知识点

提示:本文将记录遇到的C/C++问题,随时会增加


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


C/C++基础部分

  1. Q:某文件中定义的静态全局变量(或称静态外部变量)其作用域是?
    A:通常分析变量都是从两个方向分析。1、生命周期,普通局部变量的生命周期为该域的起止,全局变量和静态本地变量生命周期是程序运行的全过程。2、作用域,局部变量的作用域为定义改变量的域中,静态局部变量改变的是生命周期。全局变量生命周期为程序运行的全过程,静态全局变量限制其作用域为本文件。并且函数外的static变量不能被extern到别的文件。

  2. Q:如何判断一段程序是C编译器编译还是C++编译器编译?
    A:在程序编译过程会自动添加一些宏,其中一个可用于判断是否为C++编译器编译。

	#ifdef __cplusplus		//双下划线为非人为添加的
		cout<<"cpp"<<endl;
	#else
		cout<<"C"<<endl;
	#endif`
  1. Q:C和C++的不同?
    A:C是面向过程的(也可以通过cobject一些方法编写面向对象的程序),C++是面向对象的。C体积小效率高,适合写对效率要求更加苛刻的地方。C++是C的plus所以更加的复杂和适合编写规模大的程序,侧重对象而不是过程,侧重类的设计而不是逻辑过程的设计。
  2. Q:C和C++中struct的不同点?以及C++中struct和class区别
    A:
struct保护功能能否定义函数
C不能定义函数
C++可以定义函数,but默认是public
C++classstruct
默认访问属性privatepublic
默认继承属性privatepublic
  1. Q:如何判断机器是32位还是64位?
    A:定义一个指针int* p,然后用sizeof§,返回的便是操作系统的位数。
    或者
int tmp_num=~0;
if(a>65535){
	cout<<"32bit"<<endl;
}else{
	cout<<"16 bit"<<endl;
	
  1. C/C++内存的分配方式
C语言内存区特点分析
auto 在执行函数时,函数内局部变量的存储就是在栈上,函数执行结束时内存自动释放,效率高但是空间有限。
动态内存分配,程序在运行时通过malloc申请内存,但需要手动free释放内存,使用灵活但容易泄露
全局静态区存放全局变量和静态变量,空间由系统管理,(函数外部定义的变量,在定义的时候,这个空间就已经被开辟了)程序开始执行时开辟空间,程序结束执行时回收空间,程序执行期间一直存在。
常量区存放常量,在整个程序运行期间不能改变,生命周期与程序同
代码区存放程序执行的CPU指令,我们的代码最后在编译的时候都会转化为相应的CPU指令,告诉计算机如何执行程序
C++语言内存区特点分析
auto 在执行函数时,函数内局部变量的存储就是在栈上,函数执行结束时内存自动释放,效率高但是空间有限。
new,动态内存分配,程序在运行时通过new申请内存,但需要手动delete释放内存,使用灵活但容易泄露
自由存储区就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。
全局/静态存储区全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。
常量存储区这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)
  1. Q:对于一个频繁使用的小函数,在C中和C++中怎样实现更好?
    A: C中用宏,C++用内联函数(inline)。

  2. Q:引用和指针的区别?
    A:指针不必初始化,引用必须初始化(因为指针可以改变,引用不可以改变)。引用更加安全,指针更加灵活。

  3. Q:有了malloc/free还要new/delete干嘛?
    malloc/free是C/C++的标准库函数,new/delete是C++的运算符,二者皆可动态申请内存。
    malloc/free适用于内置类型,因为其不会调用构造函数,和对应的析构,but new/delete可以。
    由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于 malloc/free。
    因此 C++语言需要一个能完成动态内存分配和初始化工作的运算符 new,以及一个能完成清理与释放内存工作的运算符 delete。
    注意 new/delete 不是库函数。

  4. Q:如果申请不到足够大的内存块,malloc和new会返回null指针,怎么处理?
    A:申请完之后判断指针是否为null,如果是,则进行相应的处理,并结束相应的程序。

  5. Q:C++是不是类型安全的?
    A:不是类型安全的,两个不同的类型可以牵制类型转换。

  6. 转移字符’'的作用?
    通常用于特殊格式的输出如\n等,同意忘记的是【+三个八进制】或者【+两个十六进制】。

  7. Q:const关键字的作用?
    A:const可以阻止对改变量的后续更改。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
    对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;`

const char* p;//p是指向const的指针,可以改变p的指向,但是不能通过P来改变指向的变量的值。
char const *p;//同上
char* const p;//p是一个指针,且不能改变指向
//其中区别可以看const在*前后。

在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;`

first::int fun()const{return 0;}

对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。
14.Q: 交换两个变量的方法
A:

a=a^b;
b=a^b;//a ^ b ^ b = a
a=a^b;//a ^ b ^ a = b
  1. Q:打印当前文件的文件名,行号,函数名
    A:`
cout<<__FILE__;//文件名
cout<<__LINE__;//行号
cout<<__FUNC__;//函数名
  1. Q:当一个类A 中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少?
    A:是1.深度探索c++对象模型中是这样说的: 那是被编译器插进去的一个char ,使得这个class的不同实体(object)在内存中配置独一无二的地址。 也就是说这个char是用来标识类的不同对象的。
  2. Q: 为什么A++不能是左值?
    A:首先对于i++的实现是:
int   temp; 
temp   =   i;
i   =   i+1;
return   temp;  

而++i的实现是:

 i   =   i+1;
 return   i;     

所以对于我们提出来的问题已经能得到解决了:
i++=5; 是错误的是因为i++返回的是编译器自动分配的临时变量temp,而这个temp并不是你程序中定义的可寻址变量的引用 ,也就是说你不能通
过地址对temp进行操作.(换句话说就是不能作为左值),因为temp是一个临时变量。++i=5;是正确的就是因为其返回值就是i。

  1. ?:,问号后的两个操作数必须是同一类型?
    必须是同一类型。
  2. Q:内联函数是否做类型检查?
    A:内联函数要做参数类型检查, 这是内联函数跟宏相比的优势。
  3. 函数 assert 的用法?
    A:断言assert是仅在debug版本起作用的宏,用于检查“不应该“发生的情况。
    程序员可以把assert看成一个在任何系统状态下都可以安全使用的无害测试手段。
  4. Q:const 与 #define 的比较 ,const有什么优点?
    A:(1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。
    而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应) 。
    (2)有些集成化的调试工具可以对 const 常量进行调试,但是不能对宏常量进行调试。
  5. Q:
void * ( * (*fp1)(int))[10]; //fp1是一个指针,指向一个函数,这个函数的参数为int型,函数的返回值是一个指针,这个指针指向一个数组,这个数组有10个元素,每个元素是一个void*型指针。
float (*(* fp2)(int,int,int))(int);//fp2是一个指针,指向一个函数,这个函数的参数为3个int型,函数的返回值是一个指针,这个指针指向一个函数,这个函数的参数为int型,函数的返回值是float型。
int (* ( * fp3)())[10](); //fp3是一个指针,指向一个函数,这个函数的参数为空,函数的返回值是一个指针,这个指针指向一个数组,这个数组有10个元素,每个元素是一个指针,指向一个函数,这个函数的参数为空,函数的返回值是int型。
  1. Q:你觉得如果不使用常量,直接在程序中填写数字或字符串,将会有什么麻烦?
    A:1) 程序的可读性(可理解性)变差。程序员自己会忘记那些数字或字符串是什么意思,用户则更加不知它们从何处来、表示什么。
    (2) 在程序的很多地方输入同样的数字或字符串,难保不发生书写错误。
    (3) 如果要修改数字或字符串,则会在很多地方改动,既麻烦又容易出错。

C++特性

  1. Q:面向对象的三个基本特征。
    A:封装:
    把客观事物封装成类,对自身的数据和函数进行保护。
    继承:
    为了代码复用,广义的继承分三类:实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。
    多态:是将父对象设置成为和一个或更多的与他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
    简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

  2. Q: 多态的作用?
    A:隐藏实现细节,接口重用。

  3. Q:虚函数表。
    A:虚函数表是在编译时期建立的一个组织虚函数入口地址的数组。但是对象的虚指针是在运行期间(构造函数被调用时)进行初始化的。这是多态实现的关键。

  4. 虚函数。
    用一代指针调用:
    两代:
    父类虚函数,子类非虚函数,则调用父类。
    父类非虚函数,子类虚函数,则调用父类。
    三代:
    一代非虚函数,二三代虚函数,调用一代。
    一代虚函数,二三无所谓,调用三代。
    用二代指针调用:
    一代或二代虚函数,三代无所谓,调用三代。

  5. C++中有没有纯虚构造函数?
    A:构造函数不能是虚的,只能有虚的析构函数

  6. Q:析构函数和虚函数的用法和作用?
    A:析构函数是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载,只有在类对象的生命期结束的时候,由系统自动调用。有释放内存空间的作用。虚函数是C++多态的一种表现, 使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。
    派生类的析构函数必须是虚函数,否则会内存泄漏

  7. Q:通常不能声明为虚函数的有?
    A:普通函数非成员函数)、静态成员函数、内联成员函数、构造函数、友元函数。

  8. Q:重载(overload)、重写(override,有的书也叫做“覆盖”)、重定义(redefinition)的区别?
    A:重载 同一名字空间 是指允许存在多个同名函数,而这些函数的参数表不同。
    重写/覆盖 不同名字空间,用于继承,子类重新定义父类虚函数的方法。
    重定义/隐藏 不同名字空间 用于继承,派生类与基类的函数同名,屏蔽基类的函数。

  9. 全局变量的初始化,不是由 main 函数引起的。

  10. Q:① return String(s1 + s2); 和 ②String temp(s1 + s2); return temp; 一样吗?
    A:①这是临时对象的语法,表示“创建一个临时对象并返回它” 。
    ②将发生三件事。首先,temp 对象被创建,同时完成初始化;然后拷贝构造函数把 temp 拷贝到保存返回值的外部存储单元中;最后,temp 在函数结束时被销毁(调用析构函数) 。
    然而“创建一个临时对象并返回它”的过程是不同的,编译器直接把临时对象创建并初始化在外部存储单元中,省去了拷贝和析构的化费,提高了效率。

  11. Q:在 C++的一个类中声明一个 static 成员变量有没有用?
    A:改变量是所有实例所共享,也就是无论多少个实例,该变量只有一份,属于类,不被继承。而类的静态成员函数也只能访问静态成员(变量或函数)。静态成员函数不可重写,通过类名调用。

  12. Q:函数模板和类模板的区别?以及模板类
    A:函数模板通过调用时参数的类型指定,用于函数的声明和函数实现中。类模板需要程序员显式指定,同样用于数据的类型参数化。
    “一般来讲,类模版是结构相似但不同的类的抽象,是描述性的;形式:template class 类版名;模版类是 类模版铸造出来的类,是具体的类,是如结构等相似的类型;” 类模板只是一个抽象的描述,在应用时在内存中是不占空间的,
    而模板类是一个具体的东西!
    泛型编程。

  13. Q:C++空类默认产生哪些成员函数?
    A:

class Empty
{
public:
	Empty();//缺省构造函数
	Empty(const Empty&);//拷贝构造函数
	virtual ~Empty();//虚析构函数
	Empty& operator=(const Empty&)//赋值运算符
	Empty& operator&();//取址运算符
	const Empty& operator&()const;//const取址运算符
}
  1. Q:In C++, what does “explicit” mean?
    A:C++中的 explicit 关键字用来修饰类的构造函数,表明该构造函数是显式的,在某些情况下,我们要求类的使用者必须显示调用类的构造函数时就需要使用 explicit,反之默认类型转换可能会造成无法预期的问题。
  2. Q:所有的运算符都能重载吗?
    A:在 C++运算符集合中,有一些运算符是不允许被重载的。这种限制是出于安全方面的考虑,可防止错误和混乱。
    (1)不能改变 C++内部数据类型(如 int,float 等)的运算符。
    (2)不能重载‘.’,因为‘.’在类中对任何成员都有意义,已经成为标准用法。
    (3)不能重载目前 C++运算符集合中没有的符号,如#,@,$等。原因有两点,一是难以理解,二是难以确定优先级。
    (4)对已经存在的运算符进行重载时,不能改变优先级规则,否则将引起混乱。

其他

  1. Q:VC 中,编译工具条内的 Debug 与 Release 选项是什么含义?
    A:Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。
    Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
    Debug 带有大量的调试代码,运行时需要相应的运行库,发布模式程序紧凑不含有调试代码和信息,直接可以运行(如果不需要运行库)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值