您的位置:首页 > 编程语言 > C语言/C++

C++面试题知识点总结

2018-07-15 17:47 113 查看

1. 内联函数

类内定义的成员函数将自动成为内联函数,一般将短小的成员函数作为内联函数;类外定义的成员函数若要作为内联函数,仅需在返回类型前增加关键字inline;

类外定义的成员函数的格式: 返回类型 类名::函数名(参数列表)

优势:inline是用空间换取时间,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么就没必要去定义内联。所以,如果函数体代码过长、函数体有循环语句、if语句、switch语句、递归时,不宜用内联。

2. 友元函数

类的非成员函数不能直接访问类的私有数据成员,但友元函数可以,即它的访问权限与成员函数相同,但其不能用成员运算符来访问;

创建友元函数:将函数原型放入类声明中,并在原型前加入关键字friend;在类外定义不需要在函数名前指定类作用域运算符;

3. 函数重载

使用户能够定义多个名称相同但特征标(参数列表)不同的函数;

将此概念继续应用在运算符上,可重载运算符;operator[ ] ()函数将重载[ ]运算符。

4. map方法

map是STL的一個容器,以模板的方式实现,所以可以存储任意类型的变量。Map内部以二叉链表的形式存储各个变量,自建了一棵二叉树。其类似于Python中的字典数据结构。

[code]    map<int, string> map_data;//变量声明
map<int, string> map_data = { { 1, "yu" },{ 2, "yu" } };//变量初始化

5. xml即可扩展标记语言

xml是互联网数据传输的重要工具,它可以跨平台进行数据交互,它可以跨操作系统,也可以跨编程语言的平台,不受编程语言和操作系统的限制,可以说它是一个拥有互联网最高级别通行证的数据携带者。

6. 文件输出的步骤

a.#include <fstream>

b.创建一个ofstream对象;

c.将对象与文件关联起来,使用open()方法;

d.类似使用cout使用ofstream对象;

读取文件的步骤:

a.#include <fstream>

b.创建一个ifstream对象;

c.将对象与文件关联起来,使用open()方法;

d.类似使用cin使用ifstream对象;

e.#include<cstdlib>  使用is_open()判断文件是否成功打开;

使用good()方法判断读入数据是否发生错误;

使用eof()方法判断是否到达文件尾(EOF);

使用fail()方法判断EOF类型是否匹配;

7. 析构函数

    在类对象过期时自动调用析构函数,用于完成释放对象内存。类内函数原型声明,类外定义

[code]    Stock::~Stock()
{ }

8. 派生类

派生类需要添加自己的构造函数、析构函数;可根据需要额外添加数据成员和成员函数;

9. 访问控制:protected

因为子类不能直接访问基类中的私有数据成员,需要通过基类的方法才可以访问。此时,可以在基类中定义protected部分中的类成员,使得子类可以直接访问此基类中的数据成员。其在基类中,与private部分中的数据成员作用一样。

10. 多维数组的表示

[code]    int a[][2] = { { 1,2},{ 3,4 } }; //必须指定除第一维以外的所有维度

a;//二维数组的首地址

*(a);//第一行数组的首地址

*(a+ 1);//第二行数组的首地址

*(a+ 1) + 1;//第二行第二个元素的地址

*(*(a+ 1) + 1);//第二行第二个元素的值

(*p)[1];//第一行第二个元素的值,p是二级指针

11. 各数据类型的占用字节

[code]Char   1;     short  2;     int    2/4(32位机器/8); float  4;

long   4;     double 8;      longdouble  8;

12. 类占用字节

a.类占用字节只与数据成员占用字节和虚函数指针占用字节有关,而与成员函数和静态数据成员无关;

b.虚函数由于要维护一个虚函数表,所以需占用一个指针,也就是4个字节;

c.指针数据成员占用4个字节;

d.类的总大小遵守对齐规则;类或者结构体的自身对齐值是其成员中占用字节最大的那个;数据成员自身对齐值是其数据类型占用字节;

e.共用体占用字节是对齐大小的整数倍,且不能小于最大成员占用字节数

f.枚举型变量可以看做是整型,占用4个字节

12. break、continue

Break:仅使用于循环体和switch语句中,应用在循环体中来跳出循环;应用在switch语句中,使程序仅执行特定部分代码。

Continue:使程序跳过当前循环过程中的剩余代码,执行下个循环。

13. C语言中的字符常量和转义字符常量

字符常量:单引号括起来的字符, ‘a’

转义字符常量: ‘\n’换行     ‘\b’退格  ‘\ddd’转任意字符为三位八进制数  

‘\xhh’转任意字符为两位十六进制数 ‘\0’空值

14. new delete malloc free关系

malloc free是C++/C语言的标准库函数;new delete是C++语言的运算符;它们都可用于申请动态内存和释放内存。与new对应的delete会调用对象的析构函数,而与malloc对应的free只会释放内存。

[code]    int *pt = newint;   delete pt;
int *arr = newint[3];   delete[] arr;
int node = (int *)malloc(sizeof(int));  free(node);

15. C++面向对象的特点

封装(代码模块化)、多态(接口重用,派生类中重新定义基类的方法,通过虚函数实现)、继承(扩展已有的代码)

多态:方法的行为取决于调用该方法的对象,即此对象可具有多种形态。通过虚函数或者纯虚函数实现。

如果没有使用virtual关键字,则实例对象方法的行为取决于引用或指针对象的方法;

如果使用virtual关键字,则实例对象方法的行为取决于引用或指针指向的对象的方法。

[code]    school sch;//基类
person per;//派生类
school &act1 = sch;//调用school::get_data()
school &act2 = per;//调用school::get_data() 未使用virtual
school &act1 = sch;//调用school::get_data()
school &act2 = per;//调用person::get_data()使用virtual

16. 子类的构造函数和析构函数的调用顺序

定义一个对象时,先调用基类的构造函数,再调用子类的构造函数;析构时,先调用子类的析构函数,再调用基类的析构函数。

17. 虚函数、纯虚函数

在基类中的成员函数前加关键字virtual,即定义其为虚函数,则可在子类中重新定义基类方法。

纯虚函数声明的结尾处增加 =0,在基类中通过使用纯虚函数定义未实现的函数,用于在子类中对其进行定义。包含纯虚函数的类被称作抽象类,只能当做为派生其他类的基类,不能创建该类的对象。

特点:a.该基类只能被继承,不能被实例化;b.必须在派生类中实现此方法。

18. struct 和 union的区别

a. 它们都是有不同的数据类型成员组成;

b. Union中所有成员公用一块地址空间,而struct中不同成员占用不同的内存空间。

19. Const与#define的区别

Const使用场所:定义变量、修饰函数入口参数、修饰函数返回值类型

Const常量可定义数据的类型,而宏定义是没有数据类型的。编译器可对const定义的常量进行类型安全检查,而宏定义只是对字符的替换,没有类型安全检查,所以应该更多的去使用const.

20.指针和引用的区别

指针是一个新的变量,此变量存储另一个变量的地址,通过此变量来修改另一变量;

引用只是定义了另一个变量的别名,指向的还是同一个变量。

[code]int a = 1;
int &b = a;
cout <<"引用:"<< b << endl;

21.浅拷贝和深拷贝

浅拷贝指的是在复制对象成员时,仅对数据成员进行简单的赋值;

深拷贝指的是当对象中存在动态成员时,不能直接进行赋值,而需重新为其分配内存空间。

[code]    //深拷贝构造函数
Rect(constRect &r)
{
width= r.width;
height= r.height;
//为新对象重新分配动态内存空间
p= newint;
*p= *(r.p);
}
//浅拷贝构造函数
Rect(const Rect &r)
{
width= r.width;
height= r.height;
}

22. 字符数组和指针字符的区别

[code]char words[] =  "Deep Learing is very hard";
cout<< words << endl;

 打印数组名,输出的是字符数组,但数组名作为入口参数时,则指的是第一个字符的地址。

[code]char *words = "Deep Learing is very hard";
cout << words << endl;

 打印指针变量,输出的是字符串,指针变量作为入口参数时,指的是字符串的地址。

23. 线程和进程的区别

a.进程是资源分配的基本单元,而线程是系统独立调度和分配CPU运行的基本单元

b.同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包括一个线程。

c.进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束

d.线程是轻量级的进程,它的创建和销毁所需要的时间比进程小很多

e.线程中执行时一般都要进行同步和互斥,因为他们共享同一进程的所有资源

24.线程的并发和并行

并发:当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状态。

并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行。

25. 什么是多态

函数的多种形态,多态是基于继承和虚函数来实现的,声明基类对象,若未将基类成员函数声明为虚函数,则根据基类对象指向的指针类型来选择,即基类成员函数;若将基类成员函数声明为虚函数,则根据基类对象指向的对象类型来选择,即派生类成员函数。依此机制,实现了函数的多种选择方式,所以叫多态。

26. 派生类不一定非得实现基类的纯虚函数

含有纯虚函数的类是抽象类,继承此类的为派生类。若派生类实现了此纯虚函数,则此派生类可以被实例化;若派生类未实现此纯虚函数,则此派生类仍为抽象类,不能被实例化。

27. C++数据的三种内存管理

a. 自动存储区(栈)

存储局部变量,函数运行结束,则释放内存

b. 静态存储区

存储全局变量和静态变量,代码运行结束,则释放内存

c. 动态存储区(堆)

new关键则申请的内存,需手动申请,手动释放内存

28. STL vector内存扩容与释放

Vector是动态数组,有一个指针指向一片连续的内存空间,但此内存空间并不是无限大,当puch_bach()元素超过分配内存的容量时,则扩容此内存,先将元数据拷贝过去,然后释放原内存。

VS以1.5倍内存扩容:1*1.5=2(只有第一次扩容向上取整) 2*1.5=3 3*1.5=4(向下取整) 4*1.5=6 …

29. 静态联编和动态联编

静态联编:在编译阶段将函数实现和函数调用联系起来

动态联编:在执行阶段将函数实现和函数调用联系起来

30. 静态成员函数和非静态成员函数的区别

类的静态成员,在类加载的时候就会分配内存,可以通过类名(::)、对象名直接访问(.),且不传递this指针;另外,同一类的所有实例对象共享静态数据成员,可以节省内存。

类的非静态成员,在类创建实例对象时才会分配内存,只可以通过类对象名(. ->)访问.

31. #include 双引号和尖括号的区别

双引号:表示编译器先在用户的工作目录下寻找头文件,如果搜索不到,则到系统默认目录下寻找头文件,所以双引号一般用于包含自己编写的头文件。

尖括号:表示编译器只在系统默认目录或尖括号包含的目录下寻找头文件,并不去用户的工作目录下寻找,所以尖括号一般用于包括标准库文件。

 

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: