C/C++面试基本问题

 

第一部分 -----基础概念:

1.C++的三大特性:封装、继承、多态。类的基本概念:类,对象,继承。

a.封装:
封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。
封装的意义在于保护或者防止代码(数据)被我们无意中破坏。
b.继承:
继承主要实现重用代码,节省开发时间。
子类可以继承父类的一些东西。
c.多态
多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

C++中的多态是怎么实现的?

2.C和C++的区别?
答:c++在c的基础上增添类,C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制),而对于C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。


3.全局变量和局部变量在内存分配上有何不同?

全局变量保存在内存的全局存储区中,占用静态的存储单元;局部变量保存在栈中,只有在所在函数被调用时才动态地为变量分配存储单元。

4.static的作用:

a.函数体内 static 变量的作用范围为该函数体,不同于 auto 变量, 该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值

b.在模块内的 static 全局变量可以被模块内所有函数访问,但不能被模块外其他函数访问

c.在模块内的static 函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内

d.在类的static 成员变量属于整个类所拥有,对类的所以对象只有一份拷贝

e.在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的 static 成员变量

5.const解释其作用:
a.const 修饰类的成员变量,表示成员常量,不能被修改。
b.const修饰函数承诺在本函数内部不会修改类内的数据成员,不会调用其它非 const 成员函数。
c.如果 const 构成函数重载,const 对象只能调用 const 函数,非 const 对象优先调用非 const 函数。
d.const 函数只能调用 const 函数。非 const 函数可以调用 const 函数。
e.类体外定义的 const 成员函数,在定义和声明处都需要 const 修饰符

6.指针和引用的区别:

a、指针是一个实体,需要分配内存空间。引用只是变量的别名,不需要分配内存空间。
b、引用在定义的时候必须进行初始化,并且不能够改变。指针在定义的时候不一定要初始化,并且指向的空间可变。(注:不能有引用的值不能为NULL)
c、有多级指针,但是没有多级引用,只能有一级引用。
d、指针和引用的自增运算结果不一样。(指针是指向下一个空间,引用时引用的变量值加1)
e、sizeof 引用得到的是所指向的变量(对象)的大小,而sizeof 指针得到的是指针本身的大小。
f、引用访问一个变量是直接访问,而指针访问一个变量是间接访问。

7.智能指针:

当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝;另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享。

智能指针的一种通用实现技术是使用引用计数。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。

每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。

8.简述深拷贝和浅拷贝的区别:

a.在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的;但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象,所以,此时,必须采用深拷贝。
b.深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。简而言之,当数据成员中有指针时,必须要用深拷贝。

9.编写my_strcpy函数,实现与库函数strcpy类似的功能,不能使用任何库函数;
char *strcpy(char *strDest, const char *strSrc)
{
if ( strDest == NULL || strSrc == NULL)
return NULL ;
if ( strDest == strSrc)
return strDest ;
char *tempptr = strDest ;
while( (*strDest++ = *strSrc++) != ‘’);
returntempptr ;
}

10.请讲述堆和栈的区别:

a.申请方式不同。栈上有系统自动分配和释放;堆上有程序员自己申请并指明大小;

b.栈是向低地址扩展的数据结构,大小很有限;堆是向高地址扩展,是不连续的内存区域,空间相对大且灵活;

c.栈由系统分配和释放速度快;堆由程序员控制,一般较慢,且容易产生碎片;

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

a.生命周期不同:

全局变量随主程序创建和创建,随主程序销毁而销毁

局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在; 内存中

分配在全局数据区

b.使用方式不同:通过声明后全局变量程序的各个部分都可以用到;局部变量只能在局部使用,分配在栈区

操作系统和编译器通过内存分配的位置来知道的,全局变量分配在全局数据段并且在程序开始运行的时候被加载。局部变量则分配在堆栈里面 

12.new、delete、malloc、free之间的关系:

new/delete,malloc/free都是动态分配内存的方式

a.malloc对开辟的空间大小严格指定,而new只需要对象名

b.new为对象分配空间时,调用对象的构造函数,delete调用对象的析构函数

既然有了malloc/free,C++中为什么还需要new/delete呢?

因为malloc/free是库函数而不是运算符,不能把执行构造函数和析构函数的功能强加于malloc/free

13.虚函数是怎么实现的:

每一个含有虚函数的类都至少有有一个与之对应的虚函数表,其中存放着该类所有虚函数对应的函数指针(地址),

类的示例对象不包含虚函数表,只有虚指针;

派生类会生成一个兼容基类的虚函数表。

14.什么是内存泄漏?面对内存泄漏和指针越界,你有哪些方法?

动态分配内存所开辟的空间,在使用完毕后未手动释放,导致一直占据该内存,即为内存泄漏。

方法:malloc/free要配套,对指针赋值的时候应该注意被赋值的指针是否需要释放;使用的时候记得指针的长度,防止越界

a.类的构造函数和析构函数中new和delete没有配套

b.在释放对象数组时没有使用delete[],使用了delete

c.没有将基类的析构函数定义为虚函数,当基类指针指向子类对象时,如果基类的析构函数不是virtual,那么子类的析构函数将不会被调用,子类的资源没有正确释放,因此造成内存泄露

d.没有正确的清楚嵌套的对象指针

15.关于构造函数和析构函数:

https://blog.csdn.net/ladybai/article/details/50846639

第二部分-----基本算法

最长公共子序列

背包算法

排序

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值