面试了(C++)

C++面试

一、关键字

1. extern关键字作用

extern置于变量或函数前,用于标示变量或函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。它只要有两个作用:

  • 当它与"C"一起连用的时候,如:extern "C" void fun(int a,int b);则告诉编译器在编译fun这个函数时候按着C的规矩去翻译,而不是C++的(这与C++的重载有关,C++语言支持函数重载,C语言不支持函数重载,函数被C++编译器编译后在库中的名字与C语言的不同)
  • 当extern不与"C"在一起修饰变量或函数时,如:extern int g_Int;它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块或其他模块中使用。记住它是一个声明不是定义!也就是说B模块(编译单元)要是引用模块(编译单元)A中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,它会在连接时从模块A生成的目标代码中找到此函数。
2.const的作用
  1. const 修饰类的成员变量,表示成员常量,不能被修改。

  2. const修饰函数承诺在本函数内部不会修改类内的数据成员,不会调用其它非 const 成员函数。

  3. 如果 const 构成函数重载,const 对象只能调用 const 函数,非 const 对象优先调用非 const 函数。

  4. const 函数只能调用 const 函数。非 const 函数可以调用 const 函数。

  5. 类体外定义的 const 成员函数,在定义和声明处都需要 const 修饰符。。

3. C++中类与结构体的区别?
  • 最本质的一个区别就是默认的访问控制: struct作为数据结构的实现体,它默认的数据访问控制是public的,而class作为对象的实现体,它默认的成员变量访问控制是private的。
  • “class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。

二、C++特性

1. 内联函数,宏定义和普通函数的区别
  • 内联函数要做参数类型检查,这是内联函数跟宏相比的优势
  • 宏定义是在预编译的时候把所有的宏名用宏体来替换,简单的说就是字符串替换, 内联函数则是在编译的时候进行代码插入,编译器会在每处调用内联函数的地方直接把内联函数的内容展开,这样可以省去函数的调用的压栈出栈的开销,提高效率。
  • 内联函数是指嵌入代码,就是在调用函数的地方不是跳转,而是把代码直接写到那里去。对于短小简单的代码来说,内联函数可以带来一定的效率提升,而且和C时代的宏函数相比,内联函数 更安全可靠。可是这个是以增加空间消耗为代价的
  • const与#define的区别:宏在预处理阶段替换,const在编译阶段替换;宏没有类型,不做安全检查,const有类型,在编译阶段进行安全检查
2. C++内存管理

: 存放函数参数以及局部变量 , 在出作用域时 , 将自动被释放 . 栈内存分配运算内置于处理器的指令集中 , 效率很高 , 但分配的内存容量有限 .

**😗*new 分配的内存块 ( 包括数组 , 类实例等 ), 需 delete 手动释放 . 如果未释放 , 在整个程序结束后 ,OS 会帮你回收掉

自由存储区: malloc 分配的内存块 , 需 free 手动释放 . 它和堆有些相似 .

全局/静态区: 保存自动全局变量和static变量(包括static全局和局部变量)。静态区的内容在整个程序的生命周期内都存在,有编译器在编译的时候分配(数据段(存储全局数据和静态数据)和代码段(可执行的代码/只读常量))。

常量存储区: 常量 (const) 存于此处 , 此存储区不可修改 .

栈与堆的区别:

管理方式不同: 栈是编译器自动管理的,堆需手动释放

空间大小不同: 在32位OS下,堆内存可达到4GB的的空间,而栈就小得可怜.(VC6中,栈默认大小是1M,当然,你可以修改它)

能否产生碎片不同:对于栈来说,进栈/出栈都有着严格的顺序(先进后出),不会产生碎片;而堆频繁的new/delete,会造成内存空间的不连续,容易产生碎片.

生长方向不同:栈向下生长,以降序分配内存地址;堆向上生长,以升序分配内在地址.

分配方式不同:堆动态分配,无静态分配;栈分为静态分配和动态分配,比如局部变量的分配,就是动态分配(alloca函数),函数参数的分配就是动态分配(我想的…).

分配效率不同:栈是系统提供的数据结构,计算机会在底层对栈提供支持,进栈/出栈都有专门的指令,这就决定了栈的效率比较高.堆则不然,它由C/C++函数库提供,机制复杂,堆的效率要比栈低得多.

可以看出,栈的效率要比堆高很多,所以,推荐大家尽量用栈.不过,虽然栈有如此多的好处,但远没有堆使用灵活.

3. C和C++的区别?

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

4. STL库用过吗?常见的STL容器有哪些?算法用过哪几个?

STL包括两部分内容:容器和算法。(重要的还有融合这二者的迭代器)

容器,即存放数据的地方。比如array等。

在STL中,容器分为两类:序列式容器和关联式容器。

序列式容器,其中的元素不一定有序,但都可以被排序。如:vector、list、deque、stack、queue、heap、priority_queue、slist

关联式容器,内部结构基本上是一颗平衡二叉树。所谓关联,指每个元素都有一个键值和一个实值,元素按照一定的规则存放。如:RB-tree、set、map、multiset、multimap、hashtable、hash_set、hash_map、hash_multiset、hash_multimap

下面各选取一个作为说明。

vector:它是一个动态分配存储空间的容器。区别于c++中的array,array分配的空间是静态的,分配之后不能被改变,而vector会自动重分配(扩展)空间。

set:其内部元素会根据元素的键值自动被排序。区别于map,它的键值就是实值,而map可以同时拥有不同的键值和实值。

算法,如排序,复制……以及个容器特定的算法。这点不用过多介绍,主要看下面迭代器的内容。

迭代器是STL的精髓,我们这样描述它:迭代器提供了一种方法,使它能够按照顺序访问某个容器所含的各个元素,但无需暴露该容器的内部结构。它将容器和算法分开,好让这二者独立设计。

5. 解释下封装、继承和多态?

一、封装:

封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。

封装的意义在于保护或者防止代码(数据)被我们无意中破坏。

二、继承:

继承主要实现重用代码,节省开发时间。

子类可以继承父类的一些东西。

三、多态

多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

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

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

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

7. C++文件编译与执行的四个阶段

1)预处理:根据文件中的预处理指令来修改源文件的内容

2)编译:编译成汇编代码

3)汇编:把汇编代码翻译成目标机器指令

4)链接:链接目标代码生成可执行程序

8. STL中unordered_map和map的区别

map是STL中的一个关联容器,提供键值对的数据管理。底层通过红黑树来实现,实际上是二叉排序树和非严格意义上的二叉平衡树。所以在map内部所有的数据都是有序的,且map的查询、插入、删除操作的时间复杂度都是O(logN)。

unordered_map和map类似,都是存储key-value对,可以通过key快速索引到value,不同的是unordered_map不会根据key进行排序。unordered_map底层是一个防冗余的哈希表,存储时根据key的hash值判断元素是否相同,即unoredered_map内部是无序的。

操作系统

1. 线程和进程

定义

线程,有时称为轻量级进程,是CPU使用的基本单元;它由线程ID、程序计数器、寄存器集合和堆栈组成。它与属于同一进程的其他线程共享其代码段、数据段和其他操作系统资源(如打开文件和信号)。

四种状态

新生状态、可执行状态、运行状态、阻塞状态、死亡状态

线程和进程的区别和联系

1、 线程是进程的一部分,所以线程有的时候被称为是轻权进程或者轻量级进程。
2、 一个没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个进程,进程的执行过程不是一条线(线程)的,而是多条线(线程)共同完成的。
3、 系统在运行的时候会为每个进程分配不同的内存区域,但是不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源。那就是说,出了CPU之外(线程在运行的时候要占用CPU资源),计算机内部的软硬件资源的分配与线程无关,线程只能共享它所属进程的资源。
4、 与进程的控制表PCB相似,线程也有自己的控制表TCB,但是TCB中所保存的线程状态比PCB表中少多了。
5、 进程是系统所有资源分配时候的一个基本单位,拥有一个完整的虚拟空间地址,并不依赖线程而独立存在。

进程间的通信方式

管道、有名管道、信号、共享内存、消息队列、信号量、套接字、文件.

线程同步和线程互斥的区别

线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。

用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。

内核模式下的方法有:事件,信号量,互斥量。

线程同步的方式

互斥锁、条件变量和信号量

计算机网络

使用过的 shell 命令

cp , mv , rm , mkdir , touch , pwd , cd , ls , top
cat , tail , less , df , du , man , find , kill , sudo

TCP和UDP通信的差别?什么是IOCP?

  1. TCP面向连接, UDP面向无连接的

  2. TCP有保障的,UDP传输无保障的

  3. TCP是效率低的,UDP效率高的

  4. TCP是基于流的,UDP基于数据报文

  5. TCP传输重要数据,UDP传输不重要的数据

IOCP全称I/O Completion Port,中文译为I/O完成端口。

IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序。

与使用select()或是其它异步方法不同的是,一个套接字[socket]与一个完成端口关联了起来,然后就可继续进行正常的Winsock操作了。然而,当一个事件发生的时候,此完成端口就将被操作系统加入一个队列中。然后应用程序可以对核心层进行查询以得到此完成端口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值