c 面试题
【题目1】引用和指针有什么区别?
【解答】
(1)定义一个指针变量编译器会为它分配内存,而引用不占用任何内存;
(2)引用必须在定义时被初始化,指针不必;
(3)不存在指向空值的引用,但存在指向空值的指针。
【题目2】函数参数传递中值传递、地址传递、引用传递有什么区别?
【解答】
(1) 值传递,会为形参重新分配内存空间,将实参的值拷贝给形参,形参的值不会影响实参的值,函数调用结束后形参被释放;
(2) 引用传递,不会为形参重新分配内存空间,形参只是实参的别名,形参的改变会影响实参的值,函数调用结束后形参不会被释放;
(3) 地址传递,形参为指针变量,将实参的地址传递给函数,可以在函数中改变实参的值,调用时为形参指针变量分配内存,结束时释放指针变量。
【题目3】static关键字有什么作用?
【解答】
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时维持上次的值;
(2)在模块内的static全局变量可以被模块内所用函数调用,但不能被模块外其他函数访问;
(3)在模块内的static函数只能被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内;
(4)在类中的static成员变量属于整个类拥有,对类的对象只有一份拷贝;
(5)在类中的static成员函数属于整个类拥有,这个函数不接收this指针,因而只能访问static成员变量。
【题目4】const关键字有什么作用?
【解答】
(1)阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它初始化,因为以后就没机会改变它了;
(2)对指针来说,可以指定指针本身为const,也可指定指针所指的数据为const,或二者同时指定为const;
(3) 在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4) 对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
(5) 对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为左值。
【解答】
(1) 链表和数组都可以叫线性表,数组又叫顺序表,主要区别在于,顺序表是在内存中开辟一段连续的空间来存储数据,而链表是靠指针来连接多块不连续的空间,在逻辑上形成一片连续的空间来存储数据;
(2) 数组要求空间连续,占用总空间小,链表不要求空间连续,占用总空间大;
(3) 数组方便排序和查找,但删除和插入较慢;链表方便删除和插入,但查找较慢,不方便排序。
【解答】
int strlen(char*str)
{
for(int i=0;str[i]!=’\0’;i++);
return i;
}
【题目7】请编写能直接实现strstr()函数功能的代码
【解答】
char *strstr(char *str, const char *sub)
{
char *p;
for(int i=0;i<strlen(str);i++)
{
p=&str[i];
q=sub;
if(*p==*q)
{
p++;
q++;
if(*q==’\0’)
return&str[i];
}
}
return null;
}
【题目8】进程和线程的差别
【解答】线程是指进程内的一个执行单元,也是进程内的可调度实体。线程与进程的区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位;
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程也可以并发执行;
(3)拥有资源:进程是拥有资源的一个独立单元,线程不拥有系统资源但可以访问隶属于进程的资源;
(4)系统开销:在创建或撤销进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤销线程时的开销。
【题目9】const char * const p是什么意思?
【解答】
(1)char * constp;//常量指针,p的地址不可以修改
(2)char const*p;//指向常量的指针,指向的内容不可以改
(3)const char*p;//同char const *p
(4)const char *const p;//内容和地址都不可以改变
【题目10】memset、memcpy和strcpy的根本区别
【解答】
(1)memset用来对一段内存空间内全部设置为某个字符,一般用在对定义的字符串进行初始化为指定值;
(2)memcpy用来做内存拷贝,可以用来拷贝任何数据类型的对象,可以指定拷贝的数据长度;
(3)strcpy只能拷贝字符串,遇到’\0’就结束拷贝。
【题目11】析构函数有哪些特点?
【解答】
(1)析构函数也是特殊的类成员函数,它没有返回类型;
(2)没有参数;
(3)没有重载;
(4)public、private、protected等权限控制对析构函数无效;
(5)析构函数不能手动调用,只是在类对象生命周期结束的时候,由系统自动调用释放在构造函数中分配的资源。
【题目12】虚函数有什么作用?
【解答】
(1)虚函数的功能是使子类可以用同名的函数对父类函数进行覆盖,并且在通过父类指针调用时,如果有覆盖则自动调用子类覆盖函数,如果没有覆盖则调用父类中的函数,从而实现灵活扩展和多态性;
(2)如果是纯虚函数,则纯粹是为了在子类覆盖时有个统一的命名而已,子类必须覆盖纯虚函数,则否子类也是抽象类;
(3)含有纯虚函数的类称为抽象类,不能实例化对象,主要用作接口类。
【题目13】虚析构函数有什么作用?
【解答】
(1)析构函数的工作方式是:最底层的派生类的析构函数最先被调用,然后调用每一个基类的析构函数;
(2)在C++中,当一个派生类对象通过使用一个基类指针删除,而这个基类有一个非虚的析构函数,则可能导致运行时派生类不能被销毁。然而基类部分很有可能已经被销毁,这就导致“部分析构”现象,造成内存泄漏;
(3)给基类一个虚析构函数,删除一个派生类对象的时候就将销毁整个对象,包括父类和全部的派生类部分。
【题目14】分别给出bool、int、float、指针变量与零值比较的if语句
【解答】
(1)bool型变量:if(!var)
(2)int型变量:if(var==0)
(3)float型变量:
const float EPSINON=0.000001;
if((x>=- EPSINON)&&(x<= EPSINON))
(4)指针变量:if(var==NULL)
【题目15】以下为windows NT下32位C++程序,请计算sizeof的值
(1) void Func(charstr[100])
{
sizeof(str)=?
}
(2) void *p=malloc(100);
sizeof(p)=?
(3) int a[100];
sizeof(a)=?
(4)char *p=”aaaaaaa”;
sizeof(p)=?
【解答】
(1) 4
(2) 4
(3) 400
(4) 4
【题目16】写一个函数返回1+2+3+…+n的值
【解答】
int Sum(int n)
{
return ((long)1+n)*n/2;//或return (1+n)*n/2;
}
【题目17】深度遍历二叉树
【解答】
(1)深度优先搜索算法:沿着树的深度遍历树的节点,尽可能深地搜索树的分支;
(2)广度优先搜索算法:又叫宽度优先搜索,或横向优先搜索,是从根节点开始,沿着树的宽度遍历树的节点,如果所有节点均被访问则算法停止。
struct Node
{
Node *parent;
Node *Left,*Right;
}
voidThrough(Node *Root)
{
if(Root) printf(Root->data);
if(Root->Left!=null)Through(Root->Left);//左
if(Root->Right!=null)Through(Root-> Right);//右
}
【题目18】C++中的inline内联函数与普通函数的区别
【解答】
(1)所谓“内联函数”就是将很简单的函数内嵌到调用它的程序代码中,这样做的目的是节约原本函数调用时的时空开销,但作为内联函数,函数体必须十分简单,不能含有循环、条件、选择等复杂的结构;
(2)内联函数和宏的区别在于,宏是由预处理器对宏进行替代,而内联函数是通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时候内联函数像宏一样展开,所以取消了函数的参数压栈,减少了调用的开销。可以像调用函数一样调用内联函数,而不必担心会产生处理宏的一些问题。
(3)可以用inline来定义内联函数,不过,任何在类的说明部分定义的函数都会被自动的认为是内联函数。内联函数必须是和函数体声明在一起才有效。
【题目19】C++重写、重载、重定义的区别?
【解答】
(1)成员函数重载特征:
a.相同的范围,在同一个类
b.函数名字相同
c.参数不同
(2)重写(覆盖)是指派生类函数覆盖基类函数,特征是:
a.不同的范围,分别位于基类和派生类中
b.函数的名字相同
c.参数相同
d.基类函数必须有virtual关键字
(3)重定义(隐藏)是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
a.如果派生类的函数和基类的函数同名,但是参数不同,此时不管有无virtual,基类的函数被隐藏;
b.如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字,此时基类函数被隐藏。
【题目20】一个数据成员是否可以既是const又是static,如果不行,为什么?
【解答】
(1)一个数据成员可以既是const又是static,表示为静态常量;
(2)常量一般在构造函数后初始化;
(3)静态成员一般在类外初始化;
(4)静态常量在类外初始化,但要在类外初始化的同时声明为const。
【题目21】构造函数与析构函数的异同点
【解答】
1.构造函数有如下特点:
(1)构造函数的名字必须与类名相同;
(2)构造函数可以有任意类型的参数,但不能有返回类型;
(3)定义对象时,编译系统会自动调用构造函数;
(4)构造函数是特殊的成员函数,函数体可以在类体内也可以在类体外;
(5)构造函数被声明为公有函数,但它不能像其他成员函数那样被显式调用,它是在定义对象的同时被调用的。
2.析构函数有如下特点:
(1)析构函数的名字必须与类名相同,但它前面必须加一个波浪号;
(2)析构函数没有参数,也没有返回值,而且不能被重载,因此在一个类中只能有一个析构函数;
(3)当撤销对象时,编译系统会自动调用析构函数;
(4)析构函数可以是virtual,而构造函数不能是虚函数。
【题目22】自动调用复制构造函数的几种情形
【解答】
1.复制构造函数的功能是用一个已知对象来初始化另一个同类的对象。复制构造函数其实也是类的构造函数,与类名相同,有且只有一个参数,是该类对象的引用;每个类必须有一个复制构造函数。如果定义类的时候没有编写,编译器编译时会自动生成一个复制构造函数。
2.复制构造函数在三种情况下会自动被调用:
(1)当类的一个对象去初始化该类的另一个对象时;
(2)如果函数的形参是类的对象,调用函数进行形参和实参结合时;
(3)如果函数的返回值是类对象,函数调用完成返回时。
【题目23】类型转换构造函数是什么?举个例子。
【解答】
类型转换构造函数就是自动调用类型匹配的构造函数,自动将基本数据类型转换成对象。例子如下:
#include<iOStream>
using namespacestd;
class Person{
public:
double height;
Person(double h){height=h;}
};
void main()
{
Person yaoming=2.3;
cout<<yaoming.height<<endl;
}
【题目24】简述C++异常处理方式
【解答】
一个典型的C++异常处理包含以下几个步骤:
(1)程序执行时发生错误;
(2)以一个异常对象(最简单是一个整数)记录错误的原因及相关信息;
(3)程序监测到这个错误(读取异常对象);
(4)程序决定如何处理错误;
(5)进行错误处理,并在此后恢复/终止程序的执行。
【题目25】成员函数和友元函数的区别
【解答】
(1)成员函数是类定义的一部分,通过特定的对象来调用。成员函数既可以隐式访问调用对象的成员,而无须使用成员操作符;
(2)友元函数不是类的组成部分,因此被称为直接函数调用。友元函数不能隐式访问类成员,而必须将成员操作符用于作为参数传递的对象。
【题目26】C++中哪些运算符不可以重载?
【解答】
不能重载的5个运算符:
(1) .
(2) ?:
(3) sizeof
(4) ::
(5) *
【题目27】如何重载前++和后++运算符?
【解答】
前++不带参数,后++带一个int型参数以示区分。
iCount &operator ++()//前缀++
{
cout<<”前缀++”<<endl;
m_data++;
return *this;
}
iCount &operator ++(int)//后置++
{
cout<<”前缀++”<<endl;
iCount temp=*this;
m_data++;
return temp;
}
【题目28】请说出STL标准模板库中的几个常用类?
【解答】
数据结构 |
描述 |
实现头文件 |
向量(vector) |
连续存储的元素 |
<vector> |
列表(list) |
由节点组成的双向链表 |
<list> |
集合(set) |
由节点组成的集合 |
<set> |
栈(stack) |
后进先出的值的排列 |
<stack> |
队列(queue) |
先进先出的值的排列 |
<queue> |
映射(map) |
由{键,值}对组成的集合 |
<map> |
【题目29】函数模板与函数重载的异同?
【解答】
(1)函数的重载是指定义了几个名字相同,但参数的类型或参数的个数不同的函数;
(2)模板函数是指的几个函数的具体算法相同,而参数类型不同的函数;
(3)模板函数可以减少重载函数,但也可能引发错误。
【题目30】类型转换构造函数是什么?
【解答】
类型转换构造函数就是自动调用类型匹配的构造函数,自动将基本数据类型转换成对象。
【题目31】C++中explicit关键字有什么作用?
【解答】
explicit和构造函数一起使用,explicit指明构造函数只能显式使用,目的是为了防止不必要的隐式调用类型转换构造函数。
#include<iostream>
using namespacestd;
class Person{
int height;
public:
Person(){}
explicit Person(int h)// explicit修饰构造函数
{
height=h;
}
void display()
{
cout<<height<<endl;
}
};
void main()
{
//Person yaoming=2.3;//构造函数用explici修饰后将不能隐式调用类型转换构
//造函数
Person yaoming2(5);//可以显式调用类型构造函数
}
【题目32】C++中restrict关键字有什么作用?
【解答】
(1)restrict是用来优化的;
(2)restrict只能修饰指针,restrict修饰的指针是能够访问所指区域的唯一入口,限制多个指针指向同一地址。
【题目33】C++中常用的设计模式有哪些?
【解答】共有23种设计模式,但真正在开发中常用的模式有:
(1)Factory Method(工厂模式);
(2)Strategy(策略模式);
(3)Singleton(单例模式);
(4)Iterator(迭代器模式);
(5)Abstract Factory(抽象工厂模式);
(6)builder(建造者模式);
(7)Adapter(适配器模式);
(8)Bridge(桥接模式);
(9)Composite(组合模式);
(10)interpreter(解释器模式);
(11)command(命令模式);
(12)Mediator(中介者模式);
(13)Observer(观察者模式);
(14)State(状态模式);
(15)Proxy(代理模式)。
【题目34】编写一个单例模式的例子
【解答】单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。该实例被所有程序模块共享。
#include<iostream>
using namespacestd;
classCSingleton
{
private:
CSingleton(){}//构造函数是私有的
static CSingleton *m_pinstance;// static
public:
static CSingleton *GetInstance()//static
{
if(m_pInstance==NULL)//判断是否第一次调用
m_pInstance=newCSingleton();
return m_pInstance;
}
};
CSingleton * CSingleton::m_pInstance=NULL;//static属性类外初始化
void main()
{
CSingleton *p1= CSingleton:: GetInstance();
CSingleton *p2= CSingleton:: GetInstance();
cout<<(p1==p2)<<endl;//结果为true表示单例
}
【题目35】面向对象的三大特征是什么?
【解答】面向对象的三个基本特征:封装、继承、多态。
【题目36】什么是封装?
【解答】
(1)封装是面向对象的特征之一,是对象和类概念的主要特性;
(2)封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏;
(3)在C++中类中成员的属性有:public、protected、private,这三个属性的访问权限依次降低。
【题目37】什么是继承?
【解答】
(1)继承是指:可以使用现有类的所有功能,并在无须重新编写原来的类的情况下对这些功能进行扩展;
(2)通过继承创建的类称为“子类”或“派生类”;
(3)被继承的类称为“基类”、“父类”或“超类”;
(4)在某些OOP语言中,一个子类可以继承多个基类,但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现;
(5)C++中可以用public、protected、private来修饰继承特性。
【题目38】什么是多态?
【解答】
(1)多态性:允许将父类对象设置为和一个或更多的它的子对象相等的技术,赋值之后,父对象可以根据当前赋值给它的子对象的特性以不同的方式运作。简单地说,允许将子类类型的指针赋值给父类型的指针;
(2)实现多态的两种方式:覆盖、重载;
(3)覆盖:子类重新定义父类的虚函数;
(4)重载:允许存在多个同名函数,而这些函数的参数表不同。
【题目39】类与对象的区别?
【解答】
类与对象的区别,如人类与张三的区别,它们是一般与个体、抽象与具体、集体与个体的区别。
【题目40】C++中namespace是什么?
【解答】
namespace命名空间,是C++的语言特性,类似于java中的包。
【题目41】什么是可重入和不可重入函数?
【解答】
(1)什么是可重入性?
可重入函数可以由多个任务并发使用,而不必担心数据错误。相反,不可重入函数不能由多个任务共享,除非能确保函数的互斥。可重入函数可以在任意时刻被中断,稍后继续运行,不会丢失数据,可重入函数要么使用本地变量,要么使用全局变量时保护自己的数据。
(2)可重入函数
不可连续的调用持有静态数据;
不返回指向静态数据的指针,所有数据都是由函数的调用者提供;
使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据;
如果必须访问全局变量,记住利用互斥信号量来保护全局变量;
绝不调用任何不可重入函数。
(3)不可重入函数
函数中使用了静态变量,无论是全局静态变量还是局部静态变量;
函数返回静态变量;
函数中调用了不可重入函数;
函数体内使用了静态的数据结构;
函数体内调用了malloc()或者free()函数;
函数体内调用了其他标准I/O函数;
总之,如果一个函数在重入条件下使用了未受保护的共享资源,那么就是不可重入的。
相关阅读
9. C 语言 -- 循环结构:while语句和 do … while语句
本博客主要内容为 “小甲鱼” 视频课程《带你学C带你飞》【第一季】 学习笔记,文章的主题内容均来自该课程,在这里仅作学习交流。在
上周遇到个需求是上传文件的大小不能超过5M,因为想尝试着获取准确值,所以使用了BigDecimal类来计算,而通常使用的float和double在计
我们做好了一个表格,有时需要将它拆分为若干个小的分别进行统计保存,这时就需要拆分单元格了。那么,Excel如何拆分单元格呢?现在和小
共享与专用服务器的区别:专用服务器(DEDICATED):一个客户端连接对应一个服务器进程共享服务器(SHARE):多个客户端连接对应一个服务器进程
在Excel中经常需要用到宏,有些时候宏却不能运行,这个时候就需要我们进行排错了,接下来是seo实验室小编为大家带来的excel2010 宏不能