面试常见问题

2015/07/03 C和C++基础

C++基础

1、宏定义和typdef的区别

2、宏定义和函数的区别

3、运算符的优先级

4、const和define的区别

5、C++中const有什么作用?至少说三种。

6、static有什么作用?至少说明两种

7、static全局变量与普通变量有什么区别?static局部变量和普通变量有什么区别?static函数与普通函数有什么区别?

8、sizeof与strlen有哪些区别

9、sizeof有哪些用途?

10、为什么要引入内联函数?

11、为什么不把所有的函数定义成内联函数

12、内联函数与宏有什么区别?

13、引用与指针的区别。

14、指针常量与常量指针的区别

11、数组指针与指针数组

12、函数指针和指针函数

13、什么是野指针?

14、有了malloc/free,为什么还要new/delete

15、既然new/delete的功能完全覆盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?

16、malloc和new的区别?

17、struct和class的区别

18、如何判断大小端格式

19、this指针的作用

20、变量默认初始化有什么规则

系统有时候会自动帮编程者初始化未初始化的变量,建议每个内置类型的对象都要初始化。

21、什么是变量的定义与声明

声明:没有开辟内存空间,extern

定义:开辟内存空间,还可以初始化

22、C++中有哪几种作用域

作用域是程序的一段区域,作用域用于区别变量名的不同有效范围,分为全局作用域、局部作用域和语句作用域。一个变量名可以和不同作用域中的不同实体关联。

23、局部变量与嵌套的作用域

局部变量就是具有局部作用域的变量。作用域是可以嵌套的。

#include <iostream>
using namespace std;
int main(){
	int i=2;
	{
		int i=3;
		cout<<i<<endl;  //输出3
	} 
	cout<<i<<endl;      //输出2
	system("pause");
}

24、变量有几种存储类型

存储类型是从变量的生存期来划分,分为静态存储方式和动态存储方式。

a、自动类型(auto、动态)

b、静态类型(static、静态)

c、寄存器类型(register、动态)

d、外部类型(extern、静态)

25、什么是引用

引用是对象的另一个名字,定义时必须初始化,运行过程中不能被赋值。

26、如何使用const引用与非const引用

const引用是指向const对象的引用,也可以指向非const对象,但非const引用不可以指向const对象(和const指针一样)

const引用可以读取但是不可以修改被引用对象;

非const引用可以读取、修改被引用对象的值;

27、C与C++的区别

C:结构化语言,面向过程

C++:面向对象

28、什么是匈牙利命名法

匈牙利命名法是一种编程时的命名规范。主要思想是在变量和函数名中加入前缀以增进人们对程序的理解。

变量名=属性+类型+对象描述

如okButton或者cancelButton

29、变量名有什么命名规则

变量名由字母、数字和下划线组成并且必须以字母或下划线开头,变量名不可以与保留关键字和标准库冲突。

30、条件语句有哪几种形式?

条件语句分为if、if…else和if…else if…else等3中形式

31、for循环语句的计算顺序是什么?

for(initializer;condition;expression){
	statement;
}

执行顺序是:

(1)、初始化initializer

(2)、开始循环操作、判断condition

(3)、执行statement

(4)、执行expression,在跳转到(2)

主要:如果在第一次求解condition就得到false的话,则不会执行expression

32、break语句与continue语句有什么区别?

continue语句只出现在循环语句中,不会退出循环,只会终止当次执行循环体并且进入下一次循环体执行。

break语句可以出现在循环语句和break语句中,会退出循环。

33、switch语句

char ch;

switch (ch){
case 'a':
	statement1;
	break;
case 'b':
	statement2;
	break;
case 'c':
	statement3;
	break;
default:break;
}

34、什么是递归

一个过程或函数直接或间接调用自己本身。

35、汉诺塔问题

36、输入流和输出流

C++的输入输出流是指由若干字节组成的字节序列,这些字节中的数据按顺序从一个对象传送到另一个对象。在输入操作时,字节流从输入设备(如键盘、磁盘)流向内存;在输出操作时,字节流从内存流向输出设备(如屏幕、打印机、磁盘等)。流中的内容可以是ASCII字符、二进制形式的数据、图像数据、音频等等。

实际上,在内存中为每个数据流开辟一个内存缓冲区,用来存放流中的数据。流与内存缓冲区相对应,或者可以说,缓冲区中的数据就是流。

37、什么是标准输入输出流

在C++语言中,数据的输入和输出(简写I/O)包括标准输入设备(键盘)和标准输出设备(显示器)、对在外存磁盘上的文件和对内存中指定的字符串存储空间进行输入和输出这三个方面。

包括标准输入设备(键盘)和标准输出设备(显示器)的输入输出简称为标准I/O。对在外存磁盘上的文件的输入输出简称为文件I/O。对内存中指定的字符串存储空间的输入输出简称串I/O。

标准I/O:cin,cout

常用的文件流:

ifstream–从已有的文件读

ofstream–向文件写内容

C++语言系统为实现数据的输入和输出定义了一个庞大的类库,它包括的类主要

ios,istream,ostream,iostream,ifstream,ofstream,fstream,istrstream,ostrstream,strstream

其中ios为根基类,其余都是它的直接或间接派生类。ios为根基类,它直接派生四个类:输入流类istream、输出流类ostream、文件流基类fstreambase和字符串流基类strstreambase。

输入文件流类ifstream同时继承了输入流类和文件流基类(当然对于根基类是间接继承),输出文件流类ofstream同时继承了输出流类和文件流基类。

输入字符串流类istrstream同时继承了输入流类和字符串流基类,输出字符串流类ostrstream同时继承了输出流类和字符串流基类。

输入输出流类iostream同时继承了输入流类和输出流类,输入输出文件流类fstream同时继承了输入输出流类和文件流基类,输入输出字符串流类strstream同时继承了输入输出流类和字符串流基类。

38、重载输入输出流

39、C++的文件读取与写入

(1)说明一个文件流对象(内部文件)。例如:

ifstream ifile;     //说明输入文件流对象ifile
ofstream ofile;     //说明输出文件流对象ofile

(2)打开文件,在文件流对象和磁盘文件之间建立联系。例如:

ifile.open("d:\\my_in_file.txt" );
ofile.open("d:\\my_out_file.txt");

(3)对文件进行读写操作。

顺序读写可用C++的提取运算符(»)和插入运算符(«)进行,也可以用读字符的get()和读字符串的getline()等函数进行。

(4)关闭文件。文件操作结束后,应该显式地关闭该文件,与打开文件相对应,例如:

ifile.close();
ofile.close();

将百鸡问题计算结果存入文件:

#include<fstream>
#include<iomanip>
using namespace std;
int main(){
    int i,j,k;
    ofstream ofile;                             //定义输出文件
    ofile.open("d:\\myfile.txt");               //作为输出文件打开
    ofile<<"   公鸡      母鸡      小鸡"<<endl;   //标题写入文件
    for(i=0;i<=20;i++)
        for(j=0;j<=33;j++){
            k=100-i-j;
            if((5*i+3*j+k/3==100)&&(k%3==0))            //注意(k%3==0)非常重要
            ofile<<setw(6)<<i<<setw(10)<<j<<setw(10)<<k<<endl;   //数据写入文件
        }
    ofile.close();                              //关闭文件
    return 0;
}

读出存放百鸡问题计算结果的文件:

#include<fstream>
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
    char a[28];
    ifstream ifile;                   //定义输入文件
    ifile.open("d:\\myfile.txt");     //作为输入文件打开
    int i=0,j,k;
    while(ifile.get(a[i])){           //读标题,请对比cin.get(),不可用>>,它不能读白字符
        if(a[i]=='\n') break;
        i++;
    }
    a[i]='\0';
    cout<<a<<endl;
    while(1){
        ifile>>i>>j>>k;               //由文件读入数据
        if(ifile.eof()!=0) break;     //当读到文件结束时 ifile.eof()为真
        cout<<setw(6)<<i<<setw(10)<<j<<setw(10)<<k<<endl;     //屏幕显示       
    }
    ifile.close();                    //关闭文件
    return 0;
}

38、什么是异常?

异常就是程序运行时出现的不正常,可能会导致系统无法正常运行甚至停止运行的严重情况。

39、如何抛出和捕捉异常

try->throw->catch

40、宏定义与操作符的区别

宏定义是C++的预处理命令之一,它是一个替换操作,不做计算和表达式求解,不占用内存和编译时间。

41、宏定义如何展开

宏展开是用宏定义设计的宏体去替代宏指令名,并且用实际参数一一取代形式参数。

42、include有哪几种使用方式?有什么区别?

有两种:分别是#include <>和#include “”

如果头文件名在尖括号,表示该头文件是标准头文件(系统文件),编译器会根据路径环境变量来查找特定系统路径下(也即是系统目录)的系统文件。

如果头文件名在一对引号里,那么会认为它是非系统头文件,也就是自定义的头文件,编译器会在代码源文件所在的路径查找。

43、包含头文件时如何查找头文件

标准头文件在系统文件目录下查找。用户自定义头文件依次在用户目录、C++安装目录和系统文件目录下查找。

44、如何定义纯虚函数

纯虚函数用来定义没有意义的实现,用于抽象类中需要交给派生类具体实现的方法。

45、什么是值传递

值传递将要传递的值作为一个副本传递,在函数调用时,实参把它的值传递给对应的形参,方法执行中形参值的改变不影响实参,实参的值不会发生改变。

46、值传递与引用传递的区别

47、面向对象与面向过程的区别

面向过程是一种以过程为中心的编程思想,以算法进行驱动,程序=算法+数据

面向对象是一种以对象为中心的编程思想,以消息进行驱动,程序=对象+消息

48、面向对象的特征是什么?

抽象、封装、继承、多态

49、抽象类及其用途?

包含纯虚函数的类称为抽象类。抽象类把有共同属性或方法的对象抽象成一个类。

50、如何访问静态成员?

51、派生类与基类的转换

如果有一个派生类型的对象,则可以使用它的地址对基类的指针进行赋值或初始化,也可以使用派生类或对象初始化基类的引用。

派生类总是可以转换为基类的引用类型。基类转换为派生类需要在确定安全的情况下,使用强制转换来进行转换。

52、什么是虚成员?有什么作用?

虚函数的作用是实现动态联编,当程序发现虚函数名前的关键字virtual后,会自动将其作为动态联编处理,即在程序运行时动态地选择合适的成员函数。

53、构造函数与析构函数的调用时机

构造函数和析构函数的调用时自动进行的。建立对象时会调用构造函数,而销毁对象时调用析构函数。

54、有几种继承方式?

有3种

55、继承时访问级别如何变化?

子继承的时候,通过声明为protect或者private可以降低父类的访问级别。

56、什么时候会发生函数的覆盖?

覆盖(Override)是指派生类中如果存在重新定义的函数,其函数名、参数列表、返回值类型必须同父类中的相对应被覆盖的函数严格一致。覆盖函数和被覆盖函数只有函数体不同,当派生类对象调用子类中该同名函数时,会自动调用子类中的覆盖版本,而不是父类中的被覆盖函数版本。

57、如何访问基类的成员?

58、什么是深复制和浅复制

59、什么是复制构造函数?

a、一个对象以值传递的方式传入函数体;

b、一个对象以值传递的方式从函数返回;

c、一个对象需要通过另一个对象进行初始化;

60、类型转换有哪些分类?

显式转换和隐式转换

70、什么是类型转换构造函数?

一个类的构造函数只有一个参数,而且这个参数不是该类的类型而是其他类型,这个构造函数就被称为类型转换构造函数。转换构造函数可以用来处理不同域的同一个数据值。

比如:

class Polar{
private:
	double radius;
	double angle;
};

class Rec{
private:
	double xco;
	double yco;
public:
	Rec(Polar p){     //类型转换构造函数
		float r=(float)p.getr();
		float a=(float)p.geta();
		xco=r*cos(a);
		yco=r*sin(a);
	}
};

71、静态关联与动态关联

编译系统在对程序进行编译时,即能确定调用的是哪个类对象中的函数。确定调用的具体对象的过程称为关联(binding)。

函数重载和通过对象名调用的虚函数,在编译时即可确定其调用的虚函数属于哪一个类,其过程称为静态关联(static binding)

在调用虚函数时并没有指定对象名,那么系统是怎样确定关联的呢?是通过基类指针与虚函数的结合来实现多态性的。先定义了一个指向基类的指针变量,并使它指向相应的类对象,然后通过这个基类指针去调用虚函数(例如“pt->display()”)。显然,对这样的调用方式,编译系统在编译该行时是无法确定调用哪一个类对象的虚函数的。因为编译只作静态的语法检查,光从语句形式是无法确定调用对象的。

72、什么是函数?

函数由函数名、参数、返回值类型以及一组包含操作语句的语句块组成。函数可以支持重载,程序就是由函数组成的。

73、形参与实参有什么区别?

形参是函数定义或声明的函数形式参数,调用时栈中参数,函数运行结束销毁。

实参是函数调用时传递给函数的参数,传递时要与形参一一对应。

74、C++支持参数个数不确定的函数吗?

#include <iostream>
#include <stdarg.h>
using namespace std;

int max(int n,...){
	va_list ap;
	va_start(ap,n);
	int maxnum=0;
	for(int i=0;i<n;i++){
		int temp=va_arg(ap,int);
		if(temp>maxnum)
			maxnum=temp;
	}
	va_end(ap);
	return maxnum;
}

int main(){
	cout<<max(5,12,3,4,37,45)<<endl;   //45
	system("pause");
}

75、引用形参和非引用形参有什么区别?

引用形参是将参数用参数变量的地址来进行传递

76、使用引用形参有什么问题?

#include <iostream>
using namespace std;
int func1(int &n){
	return ++n;
}
int func2(const int &n){
	return n+1;
}

int main(){
	int n1=3;
	double n2=4.5;
	const int n3=6;
	cout<<func1(3)<<endl;      //错误
	cout<<func2(3)<<endl;      //正确
	cout<<func1(n1)<<endl;     //正确
	cout<<func2(n1)<<endl;     //正确
	cout<<func1(n2)<<endl;     //错误
	cout<<func2(n2)<<endl;     //正确
	cout<<func1(n3)<<endl;     //错误
	cout<<func2(n3)<<endl;     //正确
	system("pause");
}

调用非const类型的引用形参,实参必须不是const类型的,而且实参的类型和形参的类型应当一致。调用一个有const引用的形参的函数时,如果实参不是一个变量或者类型不匹配时,函数会创建一个无名的临时变量来存储实参的值,并把这个形参作为该临时变量的引用。

77、指针形参和引用实参的区别

78、什么是类成员函数?有哪些特别的类成员函数?

类中的成员可以是数据,也可以是函数。在类中的成员函数就是类的成员函数。内联与外联

特别的类成员函数有构造函数和析构函数,复制构造函数、赋值函数等待

79、什么是静态函数?如何使用静态函数?

静态函数就是使用static关键字修饰的函数。静态函数没有this指针,只能访问静态变量。

80、静态函数能访问类的私有成员吗?

静态函数只能直接访问类的静态私有成员,不可以直接访问类的非静态私有成员。

81、一个类可以访问另一个类的私有成员吗?

使用友元类:

#include <iostream>
using namespace std;
class A;

class B{
	friend class A;
public:
	B(int n):b(n){}
	void showB(){
		cout<<b<<endl;
	}
private:
	int b;
};

class A{
public:
	A(int n):a(n){}
	void showA(B Bobj){
		cout<<a<<endl;
		cout<<Bobj.b<<endl;
	}
private:
	int a;
};

int main(){
	B b(1);
	A a(2);
	a.showA(b);
	system("pause");
}

或者外部类可以使用宏定义等特殊方法来实现访问类的私有成员:

#define private public

127、函数重载与作用域

函数重载是指在相同的作用域中,具有相同的名称而形参列表不同的多个函数。

#include <iostream>
using namespace std;
int add(int x,int y){
	return x+y;
}
float add(float x,float y){
	return x+y;
}
int main(){
	int x=1;
	float y=2.3;
	cout<<add(x,y)<<endl;    //报错 无法编译
	system("pause");
}

一定要注意是相同作用域才能重载:

void print(const string &);
void print(double);           //重载print()函数
void fooBar(int ival){
	void print(int);
	print("Value:");          //错误:不在print(const string &)作用域
	print(ival);              //正确:在print(int)作用域
	print(3.14);              //正确:使用print(n) 不在print(double)作用域
}

128、如何进行函数重载的匹配

编译器遇到对重载函数的调用时,必须确定调用哪个函数。此时编译器将实在参数与所有重载函数的参数做比较,这一过程称为参数匹配。

129、函数重载时如何实现实参的类型转换

实参类型转换的优先降序等级:精确匹配> 整型提升> 标准转换> 类类型转换;

为了估计哪个重载函数最适合,需要依次按照下列规则来判断:

(1)、精确匹配:参数匹配而不做转换,或者只是做微不足道的转换,如数组名到指针、函数名到指向函数的指针、T到const T;

(2)、提升匹配:即整数提升(如bool 到 int、char到int、short 到int),float到double

(3)、使用标准转换匹配:如int 到double、double到int、double转float、double到long double、Derived*到Base*、T*到void*、int到unsigned int;

#include <iostream>
using namespace std;
void manip(int a){
    a += 2;
    cout<<a<<endl;
}
 
void manip(float a){
    a += 1;
    cout<<a<<endl;
}

int main(){
    manip(3.14);    //错误 double转int double转float同属于标准转换 出现二义性
	char c='a';
	manip(c);       //整型提升
	int i=1;
	manip(i);       //精确匹配
	system("pause");
}

130、什么是函数模板

使用模板技术定义参数化类型的非成员函数,使得程序能够使用不同的参数类型调用相同的函数。

131、什么是类模板?

使用模板技术的类。

132、什么是容器?

容器是容纳特定类型对象的集合,因此容器中的对象必须是同一类型。主要有顺序容器和关联容器。

133、有哪几种顺序容器?

顺序容器是以严格的线性形式组织在一起的容器,包括vector、deque和list等3中顺序容器。

134、什么是迭代器的范围?

迭代器就如同一个指针,可以遍历容器中所有的元素(begin()函数和end())

135、什么是关联容器?

关联容器支持通过键值(关键字)来高效地查找和读取元素。

map的元素是“键-值”对的二元组形式,即键用作元素在map中的索引,而值则表示所存储和读取的数据。

set表示一个集合,它其中所有包含的元素的值都是唯一的。

136、什么是泛型编程?

就是独立于任何特定类实现的方式编写代码。在使用泛型程序时,需要用户提供具体程序实例所操作的类型或值。通过泛型编程,一个类或函数可以操作多个类型的对象,而这些对象之间并不存在任何关系。

C++中标准STL的容器、迭代器、算法就是很好的泛型编程的实现。由于标准库使用了泛型技术,使得该库几乎能使用任何的类型。

137、C++如何实现泛型编程

C++中泛型编程的实现是使用C++中模板技术来实现的,主要是设计函数模板和类模板。

138、有哪几种表的实现方式?

线性表实现的方式有两种:一种是顺序实现,另一种是链式实现。

139、链表有哪几种分类?

单链表、循环链表和双向链表。

140、什么是队列?

先进先出

141、什么是栈

先进后出

142、如何访问栈中的元素?

访问栈元素时,主要是针对栈顶的元素进行访问,不能直接访问其他位置的栈元素。

143、如何对树进行遍历

树的遍历通常有两种:深度优先遍历和广度优先遍历。所谓的深度优先遍历,就是先访问根结点,再逐个访问子结点。广度优先遍历,就是对树中的结点逐层进行访问。

144、如何对二叉树进行遍历

先序、中序、后序

145、如何计算二叉树的高度?

int Height(BinaryTreeNode *t){
	if(!t) return 0;                 //空树
	int hl=Height(t->LeftChild);     //左子树的高度
	int hr=Height(t->RightChild);    //右子树的高度
	if(hl>hr) return ++hl;           //将hl和hr中较大的值加上1就是树的高度
	else return ++hr;
}

通过使用后序遍历方式计算二叉树的高度。可以先计算左子树的高度hl,后计算右子树的高度hr,然后树的高则是hl和hr中较大的值加上1。

146、如何计算二叉树的结点数

147、图的实现方式有哪几种?

邻接矩阵、邻接表

148、什么是冒泡排序?

149、鸡尾酒排序(改进版的冒泡排序)

150、选择排序

151、直接插入排序

152、归并排序

153、快速排序

154、希尔排序

155、堆排序

156、什么是软件工程?

软件工程就是采用工程的概念、原理、技术和方法来开发与维护软件

157、什么是软件危机?

软件危机是指软件生产方式无法满足迅速增长的计算机软件需求,不能有效地开发大型、复杂的软件,从而导致软件开发与维护过程中出现一系列严重问题的现象。

158、软件开发模型?

包括瀑布模型、原型模型、螺旋模型和增量模型;

159、如何选择开发模型?

瀑布模型适用于需求清晰明了且时间要求宽松的软件开发项目或者规模小,需求简单,功能单一的项目。

原型模型适用于客户能提出一般性目标,但不能标出详细的输入、处理及输出需求;或开发者不能确定算法的有效性、操作系统的适应性、及人机交互的形式的项目。

螺旋模型适用于大规模软件项目,需求不明朗,风险比较高的项目。

增量模型适用于需求逐渐清晰的软件项目。

160、软件测试有哪些分类?

黑盒测试:已知产品应该具有的功能,通过测试检查每个功能是否都可以正常地使用;

白盒测试:已知产品内部的工作过程,通过测试检验产品内部逻辑流程是否按照产品的规格说明书的规定进行。

161、什么是UML

UML(Unified Modeling Language,简称UML)是一种标准的图形化建模语言,它是面向对象分析与设计的一种标准表示。

162、什么是设计模式?

设计模式是一系列在实践中总结出来的可复用的面向对象的软件设计方法

设计模式有4个要素:模式名称、问题、解决方案和效果。

163、堆与栈的区别

堆和栈的区别:

一、堆栈空间分配区别:

1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;

2、堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。

二、堆栈缓存方式区别:

1、栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放;

2、堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

三、堆栈数据结构区别:

堆(数据结构):堆可以被看成是一棵树,如:堆排序;

栈(数据结构):一种先进后出的数据结构。

164、strcpy和memcpy的区别

165、如何判断一段程序是由C编译程序还是由C++编译程序编译的?

#ifdef __cplusplus
	cout<<"c++";
#else
	cout<<"c";
#endif

166、C和C++有什么不同?

从机制上: c是面向过程的(但c也可以编写面向对象的程序); c++是面向对象的,提供了类。但是,c++编写面向对象的程序比c容易。

从适用的方向: c适合要求代码体积小的,效率高的场合,如嵌入式; c++适合更上层的,复杂的; llinux核心大部分是c写的,因为它是系统软件,效率要求极高。

从名称上也可以看出,c++比c多了+,说明c++是c的超集;那为什么不叫c+而叫c++呢,是因为c++比 c来说扩充的东西太多了,所以就在c后面放上两个+;于是就成了c++。

C语言是结构化编程语言,C++是面向对象编程语言。 C++侧重于对象而不是过程,侧重于类的设计而不是逻辑的设计。

C++由四部分组成:

1> C语言部分;

2> 面向对象部分,包括封装、继承、多态这些C语言所没有的特性;

3> 泛型编程部分,大多数类、函数要考虑到把它设计成模板,方便复用;

4> STL库,里面封装了大量的优秀模板,是 3> 中内容的集成, 学会使用它们可以让代码更高效。当然,最好去深入了解STL源码,那样会对C++有更深的理解。

167、int id[sizeof(unsigned long)];这个对吗?为什么?

正确,这个sizeof是编译时运算符,编译时就确定了,可以看成和机器有关的常量。

168、C++函数中值的传递方式有哪几种?

C++函数的三种传递方式为:值传递、指针传递和引用传递。(指针传递就是通常说的地址传递)

169、对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?

c用宏定义,c++用inline,define实现的函数功能容易出bug,所以在c++中最好不要使用

170、C++中virtual与inline的含义分别是什么?

在基类成员函数的声明前加上virtual关键字,意味着将该成员函数声明为虚函数。

inline与函数的定义体放在一起,使该函数称为内联。

inline是一种用于实现的关键字,而不是用于声明的关键字。

虚函数的特点;如果希望派生类能够重新定义基类的方法,则在基类中将该方法定义为虚方法,这样可以启用动态联编。

内联函数的特点;使用内联函数的目的是为了提高函数的运行效率。内联函数体的代码不能过长,因为内联函数省去调用函数的时间是以代码膨胀为代价的。内联函数不能包含循环语句,因为执行循环语句要比调用函数的开销大。

171、VC中,编译工具条内的Debug与Release选项是什么含义?

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

172、assert()函数用法?

assert宏的原型定义在中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:

#include <assert.h>
void assert(int expression);

assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。

173、如果在申请动态内存时找不到足够大的内存块,malloc 和 new 将返回 NULL 指针,宣告内存申请失败。你是怎么处理内存耗尽的?

(1)判断指针是否为 NULL,如果是则马上用 return 语句终止本函数。

(2)判断指针是否为 NULL,如果是则马上用 exit(1)终止整个程序的运行

174、C++是不是类型安全的?

答案:不是。两个不同类型的指针之间可以强制转换(用reinterpret cast)。C#是类型安全的。

175、用C++写个程序,如何判断一个操作系统是16位还是32位的?

定义一个指针p,打印出sizeof(p),如果节果是4,则表示该操作系统是32位,打印结果是2,表示是16位。

176、用C++写个程序,如何判断一个操作系统是16位还是32位的?不能用sizeof()函数。

int a = ~0;  
if( a>65536 )  {         
	cout<<"32 bit"<<endl;     
}else  {  
	cout<<"16 bit"<<endl;  
}  
现在大部分机器都32、64位的了,所以,应该把65536改为4294967296,来判断机器是32位   64 位

177、多态类中的虚函数表是Compile-Time,还是Run-Time时建立的? 虚拟函数表是在编译期就建立了,各个虚拟函数这时被组织成了一个虚拟函数的入口地址的数组.而对象的隐藏成员–虚拟函数表指针是在运行期–也就是构造函数被调用时进行初始化的,这是实现多态的关键。

178、内存的分配方式有几种?

一、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量。

二、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

三、从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

179、float a,b,c ,问等式 (a+b)+c==(b+a)+c 和(a+b)+c==(a+c)+b能否成立?

两者都不行。在比较float或double时,不能简单地比较。由于计算误差,相等的概率很低。应判断两数之差是否落在区间(-e,e)内。这个e应比浮点数的精度大一个数量级。我想到的是另一个运算符%。不能对float或double使用%运算符。

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

生命周期不同: 全局变量随主程序创建而创建,随主程序销毁而销毁;内存中分配在全局数据区。 局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在; 分配在栈区。

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

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

179、In C++, what does “explicit” mean? what does “protected” mean?

c++中的explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,在某些情况下,我们要求类的使用者必须显示调用类的构造函数时就需要使用explicit,反之默认类型转换可能会造成无法预期的问题。

protected控制的是一个函数对一个类的成员(包括成员变量及成员方法)的访问权限。protected成员只有该类的成员函数及其派生类的成员函数可以访问。

180、重复多次fclose一个打开过一次的FILE *fp指针会有什么结果,并请解释。

导致文件描述符结构中指针指向的内存被重复释放,进而导致一些不可预期的异常。

181、为什么数组名作为参数,会改变数组的内容,而其它类型如int却不会改变变量的值?

当数组名作为参数时,传递的实际上是地址。而其他类型如int作为参数时,由于函数参数值实质上是实参的一份拷贝,被调函数内部对形参的改变并不影响实参的值。传值与传地址的区别。

182、你觉得如果不使用常量,直接在程序中填写数字或字符串,将会有什么麻烦?

(1) 程序的可读性(可理解性)变差。程序员自己会忘记那些数字或字符串是什么意思,用户则更加不知它们从何处来、表示什么。

(2) 在程序的很多地方输入同样的数字或字符串,难保不发生书写错误。

(3) 如果要修改数字或字符串,则会在很多地方改动,既麻烦又容易出错。

183、什么需要使用堆,使用堆空间的原因?

直到运行时才知道一个对象需要多少内存空间;不知道对象的生存期到底有多长。因为需要动态分配内存啊。。。

184、32位编译器和64位编译器

32位编译器:32位系统下指针占用4字节 char :1个字节

char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)

short int : 2个字节

int: 4个字节

unsigned int : 4个字节

float: 4个字节

double: 8个字节

long: 4个字节

long long: 8个字节

unsigned long: 4个字节

64位编译器:64位系统下指针占用8字节

char :1个字节

char*(即指针变量): 8个字节

short int : 2个字节

int: 4个字节

unsigned int : 4个字节

float: 4个字节

double: 8个字节

long: 8个字节

long long: 8个字节

unsigned long: 8个字节

185、TCP三次招手和四次挥手

当某个连接的一端处于TIME_WAIT状态时,该连接将不能再被使用。fin_wait1状态是在server端主动要求关闭tcp连接,并且主动发送fin以后,等待client端回复ack时候的状态。Server端强制断开Socket时向客户端发送了FIN请求,客户端已经没有能力继续回复ACK,造成了服务器端大量的端口处在FIN_WAIT_2状态

186、大小端

0x20150810

如果按照大端模式存储:

从低地址到高地址:20 15 08 10

输出从低地址到高地址:20 15 08 10

如果按照小端模式存储:

从低地址到高地址:10 08 15 20

输出从高地址到低地址:08 10 20 15

操作系统

1、什么是进程?

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。

2、什么是线程?

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

内存管理

1.什么是虚拟空间

2.什么是地址重定位?静态重定位和动态重定位

3.什么是分区管理?

4.什么是固定分区法和动态分区法?分区说明表、可用表或自由链、请求表

5.固定分区时的分配与回收、动态分区时的分配与回收算法

6.分区管理的优缺点

7.什么是页式管理

8.静态页面管理、地址变化、页表、请求表、存储页面表

9.动态页式管理,请求页式管理置换算法

10.内存抖动现象

11.页式管理的优缺点

计算机网络

1.网络分层模型

2.IP地址的组成、分类(A、B、C)

3.IP地址与硬件地址的区别

4.地址解析协议ARP

5.IP层转发分组的过程

6.为什么要划分子网,什么是子网掩码?

7.有子网的IP分组转发过程

QT面试问题

1、什么是QT?有什么优点?

QT是诺基亚公司开发的一个跨平台的C++图形用户界面应用程序框架。它提供给开发者建立艺术集的图形用户界面所需要的功能。奥康标签(QLable)、按钮(QPushButton)、QDialog、QWiget等等。

优点:QT是完全面向对象的,就很容易扩展。同时它是一个跨平台C++图形用户界面库,具有很强的移植性,目前已经支持Linux、window、嵌入式等等用户开发界面。

2、QT中的一些继承关系

QObject->QWidget(各种窗口部件)、QLayout(负责窗口布局):

QWidget->

QFrame->QLable

QMainWindow

QDialog

QPushButton

QSpinBox

QSlider 等等

3.信号与槽机制

槽和普通的C++成员函数几乎是一样的,可以是虚函数,可以被重载,也可以是公有的、保护的或者私有的,并且也可以被其他C++成员函数直接调用,它们的参数可以是任意类型。唯一不同的是:槽可以和信号连接在一起,每当发射这个信号的时候,就会自动地调用这个槽。

算法题

1、-把二元查找树转变成排序的双向链表

2、设计包含min函数的栈,定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop 的时间复杂度都是O(1)。

3、求子数组的最大和

题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。

4、在二元树中找出和为某一值的所有路径

题目:输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶结点所经过的所有 结点形成一条路径。打印出和与输入整数相等的所有路径。

Search

    Post Directory