美文网首页
一些面试题

一些面试题

作者: 突击手平头哥 | 来源:发表于2019-12-30 21:59 被阅读0次

1, 信号的声明周期

答: 信号的产生 -> 信号在进程中注册 -> 信号在进程中的注销 -> 执行信号处理函数

2, 信号的产生方式

答: 1, bash命令行下的kill命令; 2, C中的信号发送函数kill(), sigqueue(), raise(), alarm(), setitimer(), pause(),abort()等; 3, 一些软硬件异常产生的信号

3, 信号的处理方式

答: 1, 默认处理方式, 比如PIPE信号会导致进程终止; 2, 忽略处理或者自定义函数处理(signal或者signaction函数)

4, 隐式类型转换以及如何消除?

答: 如果可以通过一个实参创建一个类, 那么我们可以隐式的完成该实参类型到该类类型的转换, 通过该构造函数前加上explicit避免这种隐式的转换

5, 重载/重写/隐藏的区别

答: 重载指的是函数的重载(函数名相同和参数不同的函数), 重写指的是虚函数, 隐藏指的是子类的函数名与父类相同就会隐藏

6, volatile功能

答: 在实际中我们可能遇到一个线程等待一个参数在另外一个线程发生改变; 但是由于代码优化每次都从寄存器中取值, 而另外线程的修改没有影响到此线程的寄存器, 导致无法检测变化; 该关键字指的就是每次从内存去取值.

7, malloc/new/free/delete区别

答: new/delete是描述符, 仅属于C++; 而后两者是库函数, C中可以使用. new错误会抛出bad_alloc异常, 而malloc失败返回NULL; new无需指明大小, 其返回的是指定的类型, malloc必须指明大小并返回void指针; new会调用构造函数, 后者不会; 都是在堆中分配释放内存.

8, free是怎么知道释放多大内存的呢?

答: 一般在分配的内存前几个字节有一个结构体保存一些信息, 在redis中实现的动态字符串就是这种形式.

-------------------2019年11月9日16点35分----------------------

9 __stdcall__cdecl的区别

答: 函数参数均从右到左入栈, 但是前者被调用的函数自行清理堆栈, 后者是主动调用该函数的进行清理堆栈。 也因此, 前者需要确定的参数数量, 不能用于变参数.

10, Linux有哪些调试宏

答: __FILE__/__LINE__/__FUNCTION__分别指明文件名/行数/函数名

11, 线程安全的单例模式

饿汉式

class Singleton
{
private:
    Singleton();
    Singleton(Singleton const &);
    Singleton & operator = (Singleton const &);
    static Singleton *instance;
public:
    static Singleton* getInstatce()
    {
        return instance;
    } 
    
};

Singleton Singleton::instance = new Singleton();

懒汉式

class Singleton
{
private:
    Singleton();
    Singleton(Singleton const &);
    Singleton & operator = (Singleton const &);
    static Singleton *instance;
    static std::mutex _mutex;
public:
    static Singleton* getInstatce()
    {
        if(nullptr == instance)
        {
            std::lock_guard<std::mutex> lk(_mutex);
            if(nullptr == instance)
            {
                instance = new Singleton();
            }
        }

        return instance;
    } 
    
};


std::mutex Singleton::_mutex;

注意:可以额外添加以静态成员用以销毁资源

12, 引用和指针的区别?

  • 1 引用只是一个别名, 必须初始化, 不占用额外空间; 指针本身就是一种数据结构可以为nullptr, 占用4/8字节
  • 2 引用只能为一个成员的引用, 指针如果不加const限制的话可以修改其指向

13, 出现异常时, trycatch分别干了什么?

答: try{}用于包含可能抛出异常的语句; catch{}用于包含处理异常的语句

14, C++如何处理多个异常

try
{
    //可能抛出异常的语句
}
catch (异常类型1)
{
    //异常类型1的处理程序
}
catch (异常类型2)
{
    //异常类型2的处理程序
}
// ……
catch (异常类型n)
{
    //异常类型n的处理程序
}

15, intptr_t的用处

答: intptr_t通常是和指针关联起来的, 再不同的平台上定义是不一样的和电脑的位数一致; 可以跨平台的用于保存指针

16, 常对象的成员变量一定不可修改吗? 为什么?

答: 常对象的成员变量不可修改, 和普通使用const修饰的基础类型一样; 尽可以调用常成员函数.

17, 虚函数的调用过程?

答: 对象指针指向的地址前四个字节存储的就是虚函数表的首地址(如果有虚函数的话), 获得了该地址即可获得所有虚函数的地址.

18, 单继承,多继承,菱形继承,虚继承时,对象内存中的差异区别?如果存在虚函数呢?

答: C++使用的对象模型: nostatic对象放置于每一个类的对象之中, static则放在类对象之外, static和nostatic也放在类对象之外, 对于virtual函数使用虚函数表+虚函数指针来支持:

1, 每一个类生成一个表格, 称为虚函数表; 用于存储一堆指针指向类的虚函数, 按照声明的顺序.

2, 每个类的对象都有一个虚函数表的指针vptr, 一般放在类对象的前端.

3, 虚函数表的前端 设置了一个指向type-info的指针, 用于dynamic_cast等运行时类型判断.

vector为什么采用成倍增长而不采用固定容量呢? VS采用1.5/GCC采用2, 为什么?

注意: 绝大多数分配时使用的时malloc再复制的方式.

答: 假设采用成倍增长:
  如果最后数量为n, 倍增因子为m, 那么需要重新分配空间的次数为logm(n), 每次复制所需的时间复杂度为m^i; 所以整的时间复杂度为:

1*m^1 + 2*m^2.....logm(n)*m^(logm(n)) = 1*m^1+2*m^2....logm(n)*n

时间复杂度是常数级.

如果采用固定容量增长:
  如果最后数量为n, 增长容量为为m, 那么需要重新分配空间的次数为n/m, 每次复制所需的时间复杂度为m*i; 所以整的时间复杂度为:

1*m*1+2*2*m..(n/m)^2*m = m+m*2^2..m*(n/m)^2

时间复杂度为O(N)

采用1.5分配的方式, 能够使得第N次分配的空间, 能够重用前N-1分配的空间. 采用2的方式可能是方便寻址.

map底层使用了什么

答: 红黑树

如果用map删除了一个元素,迭代器还能用吗?为什么?怎样做可以接着用?

答:

for(auto it = map.begin(); it != map.end();)
{
    if(xxx)
        map.erase(it++);
    else
        it++;
}
  • 如果对一个iterator使用了erase, 那么此iterator就失效了; 之后任何操作是未定义的.
  • it++会对, it进行后移操作, 同时返回原本的值; erase销毁的it已经是另外一个了.

\color{red}{扩展}: 如果对于vector呢?

for(auto it = vec.begin(); it != map.end();)
{
    if(xxx)
        vec.erase(it);          //erase后自动后移
    else
        it++;
}

线程同步的几种方式?

答: 互斥锁(mutex), 条件变量(condition_variable), 信号量(Semaphore)

Do{}while(0)的用法有哪些?

答: 通常用于仅执行一次的代码, 用于宏定义当中比较多;

手写快排?时间复杂度?空间复杂度?能进行优化吗?还有吗?能进行尾递归优化吗?

答:

void core(int num[], int r, int l)
{
    if(i >= j-1)    return;
    if(i+1==j)
    {
        if(num[i]>num[j])
            swap(num[i], num[j]);
        return;
    }

    int mid = r;
    int i = r+1;
    int j = l;
    while(i<j)
    {
        while(i<j&&num[i]<=mid) i++;
        while(i<j&&num[j]>=mid) j--;

        if(i < j)
            swap(num[i], num[j])
    }

    swap(num[k], num[j]);

    core(num, i, j-1);
    core(num, j+1, l);

}

void quick_sort(int num[], int n)
{

    if(n <= 1)  return;
    core(num, 0, n - 1);
}


//迭代做法
    while(i<j)
    {
        int k = partition(num, i, j);
        core(num, i, k-1);
        i = k+1;
    }

空间复杂度是O(1), 时间复杂度为O(nlogn),

线程池的作用是什么?

答: 减少资源开销, 提高响应速度, 同时提高管理性

TCP三次握手和四次挥手及各自的状态?

答: 三次握手

A -----CLOSE
        LISTEN------B
        ->SYN
A -----SYS_SEND
        <-ACK/SYN
        SYS_RECV----B
A ----- ESTAB-LISHED
        ->ACK   
        ESTAB-LISHED--B

四次挥手:

A ----- ESTAB-LISHED
        ESTAB-LISHED--B
        ->FIN
A ----- FIN_WAIT1
        <-ACK
        CLOSE_WAIT---B
A ----- FIN_WAIT2
        <-FIN
        LAST_ACK --- B
        ACK->
A ----- TIME_WAIT
        CLOSE--------B

TCP如果两次握手会出什么问题?那三次握手又会造成什么问题?有什么好的解决方法没?

答: 两次握手可能会导致一方建立连接而另外一方却不是; 三次握手可能引起SYN攻击

TCP四次挥手为什么要有TIME_WAIT状态?为什么?

答: 2MSL, 保证重传

排序稳定的算法,你知道那些?

答: 冒泡排序, 插入排序, 归并排序(合并时左边再前)

HASH冲突的解决办法?

答: 链表法, 再HASH法

C++内存存储

答: 堆、栈、自由存储区(new)、全局/静态存储区, 常量

如果new申请内存失败了,如何去解决?

答: bad_alloc错误

如何得到一个结构体内成员的偏移量?

答: #define offset(type, mem) ((size_t)(&(((type*)0)->mem)))

进程和线程的区别

答: 一个进程可以有多个线程, 普通程序属于单进程单线程; 不同进程间数据不可见, 同一个进程中的线程处于一块内存区.

逐层打印二叉树?

答:

void core(ListNode *root)
{
    if(!root)   return;

    print(root);
    core(root->left);
    core(root->right);
}

void print_tree(List Node *root)
{
    queue<ListNode*> _queue;
    _queue.push(root);
    while(_queue.size())
    {
        ListNode *tmp = _queue.top();
        _queue.pop();
        if(tmp->left)
            _queue.push(tmp->left);
        if(tmp->right)
            _queue.push(tmp->right);
        print(tmp);
    }
}

构造函数能不能虚函数?为什么?那拷贝构造函数能不能为虚函数?为什么?

答: 不可以为虚函数, 因为虚函数需要虚函数表; 构造函数实在对象完全构造之前运行的,但是只有创建了对量才能获得虚函数指针. 拷贝构造函数也一样

析构函数能不能虚函数?为什么?

答: 子类可能存在其自身的数据, 仅靠父类的构造函数无法完全进行.

模板和实现可不可以不写在一个文件里面?为什么?

答: 必须写在一个文件中, 模板类的实现,脱离具体的使用,是无法单独的编译的; 不同类型的调用函数其实是不一样的.

为什么要字节对齐?

答: 字节对齐, 可以提高访问效率

在成员函数中调用delete this会出现什么问题?对象还可以使用吗?

答: this所指向的空间会被释放, 但是如果不涉及到this还是可以运行的; 但是要考虑到空间虽然被释放了, 但是内容未必会被立即覆盖.

如果在构造函数中调用memset(this, 0, sizeof(*this))来初始化内存空间,有什么问题吗?

答: 的确可以使用this指针, 但是这样覆盖的话会影响虚函数表和已经初始化的数据.

对一个数组而言,delete a和delete[] a有什么区别?为什么?

答: 对于普通的数据类型没有差别, 但是对于类对象来说仅调用a[0]的析构函数.

Dynamic_cast是如何实现运行时类型转换的?

答: 没有虚函数的类型是无法判断的, 可以猜到是利用的虚函数表中的type-info数据结构来判断.

Extern “C”是什么意思?他有什么作用?

答: 表示该部分代码按照C代码格式进行编译.

进程间的通信方式有哪些?线程间的通信方式呢?

答: 进程间通讯包括socket、pipe、信号量等; 线程间数据通用, 仅需要考虑同步的问题.

IO模型主要有哪些?

答: 阻塞IO/非阻塞IO/多路复用IO

阻塞和非阻塞?同步与异步的区别?

答:
1,同步,就是我调用一个功能,该功能没有结束前,我死等结果。

  1. 异步,就是我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知)
  2. 阻塞,就是调用我(函数),我(函数)没有接收完数据或者没有得到结果之前,我不会返回。
  3. 非阻塞,就是调用我(函数),我(函数)立即返回,通过select通知调用者

Select,poll和epoll的区别?为什么?

答:
select多平台通用, epoll仅用于Linux平台
select存在连接数限制, Linux下默认是1024个; poll没有最大连接数限制, 使用的是链表
select扫描方式是轮询的, 效率较低; 当事件后也需要遍历传入的socket
select需要维护一个较大的数组, 每次传入内核.
epoll存在边缘触发(如果事件触发后不解决, 之后不再提醒), 属于事件驱动, 不需要每次复制数据到内核. 仅考虑活跃连接, 仅有活跃连接会调用回调函数。

Struct{char a[0];}的作用?有什么好处?

答: 数组扩展

Struct A a;
A *b = &a;
char buffer[128] = {};
b = buffer;

判断浮点数相等

答: abs(a-b)<1e-6

栈上分配内存和堆上分配内存有什么区别?

答: 栈的内存较少, 堆的内存加多; 栈分配的内存再代码段结束时会自动回收.

变量的存储方式有哪些?

答: C语言中的变量有四种存储类型,这四种存储类型的关键字分别是auto(自动),extern(外部),static(静态)和register(寄存器)。

register无法用于全局变量且无法取址. 速度更快.

线程私有和共享那些资源?进程私有和共享那些资源?

答: 线程共享数据: 进程代码段、进程的公有数据(利用这些共享的数据,线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID
私有数据: 线程ID;寄存器组的值;线程的堆栈;错误返回码;线程的信号屏蔽码;线程的优先级。

什么是守护进程?如何查看守护进程?什么是僵尸进程?如何查看僵尸进程?

答: 脱离控制台, 后台运行的进程; 使用ps查看. 父进程没有等待子进程就结束了, 子进程就成为了僵尸进程; 可以使用top查看.

2019年12月30日21点58分

相关文章

  • 面试相关资料

    2018 iOS面试题系列2019 iOS 面试题大全(补充完整版)面试题学习交流常见的一些面试题

  • 大厂面试为什么需要了解JVM

    如果你经常注意面试题,你会发现现在面试题多多少少会含有jvm相关的面试题,之前也把一些jvm面试题汇总了下:面试题...

  • OC面试题目合集

    这里用来记录一些OC面试题目(不定期更新, 会逐渐补充...) 视图面试题 IOS面试题(UIView) ----...

  • 10道不得不会的Docker面试题

    Docker 以下是一些docker的基础面试题,下一篇docker进阶面试题。本系列《最少必要面试题》[(htt...

  • javaSpring面试题,安排

    收藏一些关于Spring框架的面试题,一方面是为了准备找工作的时候看面试题,另一方面,通过面试题的方式加深一些自己...

  • Python面试题

    记录下比较好的Python相关的一些面试题 1.kenwoodjw在github上整理分享的一些面试题-传送门这些...

  • Android 面试题汇总

    一、Android面试题 Android面试题包括Android基础,还有一些源码级别的、原理这些等。所以想去大公...

  • Android面试

    [toc] Android面试题 Android面试题除了Android基础之外,更多的问的是一些源码级别的、原理...

  • Android面试题

    二、Android面试题 Android面试题包括Android基础,还有一些源码级别的、原理这些等。所以想去大公...

  • Android面试题

    从网络找到一些面试题,以及自己想的一些面试题,欢迎补充和吐嘈。 初级工程师 一、Java 1. ”==”和equa...

网友评论

      本文标题:一些面试题

      本文链接:https://www.haomeiwen.com/subject/ehlvoctx.html