c++面试常见问题

1、 C 和 C++ 区别:面向对象,STL模板库;

2、 const 有什么用途

主要有三点:

      1:定义只读变量,即常量 

      2:修饰函数的参数和函数的返回值 

      3: 修饰函数的定义体,这里的函数为类的成员函数,被const修饰的成员函数代表不修改成员变量的值

const 对C++成员函数的修饰分为三种:1. 修饰参数;2. 修饰返回值;3. 修饰this指针。

基本变量类型的参数作为“值传递”的输入参数,无需采用引用。自定义变量类型(class类型,struct类型)参数作为“值传递”的输入参数,最好采用"const+引用"格式,即 void func(const A& a)。原因是自定义变量类型作为值传递时,设计创建临时变量,构造,复制,析构,这些过程很消耗时间。

当占空间很大的变量作为输入型实参时,很适合用引用传递。因为用引用传递时,只是传递变量本身的一个别名,不会进行新变量的内存分配,构造,赋值,析构等操作。

以下是const成员函数注意的几点

  1)const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数.即对于class A,有

  const A a;

  那么a只能访问A的const成员函数。而对于:

  A b;

  b可以访问任何成员函数。

  2)const对象的成员变量不可以修改。

  3)mutable修饰的成员变量,在任何情况下都可以修改。也就是说,const成员函数也可以修改mutable修饰的成员变量。c++很shit的地方就是mutable和friendly这样的特性,很乱。

  4)const成员函数可以访问const成员变量和非const成员变量,但不能修改任何变量。检查发生在编译时。

  5)非const成员函数可以访问非const对象的非const数据成员、const数据成员,但不可以访问const对象的任意数据成员。

  6)const成员函数只是用于非静态成员函数,不能用于静态成员函数。

  7)const成员函数的const修饰不仅在函数声明中要加(包括内联函数),在类外定义出也要加。

  8)作为一种良好的编程风格,在声明一个成员函数时,若该成员函数并不对数据成员进行修改操作,应尽可能将该成员函数声明为const 成员函数。

3. 指针和引用的区别

    1:引用是变量的一个别名,内部实现是只读指针

    2:引用只能在初始化时被赋值,其他时候值不能被改变,指针的值可以在任何时候被改变

    3:引用不能为NULL,指针可以为NULL

    4:引用变量内存单元保存的是被引用变量的地址

    5:“sizeof 引用" = 指向变量的大小 , "sizeof 指针"= 指针本身的大小

    6:引用可以取地址操作,返回的是被引用变量本身所在的内存单元地址

    7:引用使用在源代码级相当于普通的变量一样使用,做函数参数时,内部传递的实际是变量地址

4. C++中有了malloc / free , 为什么还需要 new / delete     

 1.malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
 2.对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
 3.因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

5.不调用C/C++ 的字符串库函数,编写strcpy

 char * strcpy(char * strDest,const char * strSrc)
        {
                if ((strDest==NULL)||strSrc==NULL))                     
                   return NULL;    
                char * strDestCopy=strDest; 
                while ((*strDest++=*strSrc++)!='\0'); 
                *strDest = '\0';
                return strDestCopy;
        }

6. 编写类String 的构造函数,析构函数,拷贝构造函数和赋值函数

7. 多态的实现

C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数

  1)用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。  

  2)存在虚函数的类都有一个一维的虚函数表叫做虚表,类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是和对象对应的。

  3)多态性是一个接口多种实现,是面向对象的核心,分为类的多态性和函数的多态性。  

  4)多态用虚函数来实现,结合动态绑定。

  5) 纯虚函数是虚函数再加上 = 0。

  6) 抽象类是指包括至少一个纯虚函数的类。

8. 单链表的逆置

9. 堆和栈的区别  

 一个由c/C++编译的程序占用的内存分为以下几个部分 
  1) 栈区(stack)― 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 
  2) 堆区(heap) ― 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似      于链表。 
  3) 全局区(静态区)(static)― 全局变量和静态变量的存储是放在一块的,
     初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 
  4) 文字常量区  ―常量字符串就是放在这里的。 程序结束后由系统释放 .
  5) 程序代码区―存放函数体的二进制代码。

10、关键字static的作用

    1)  函数体内 static 变量的作用范

围为该函数体,不同于 auto 变量, 该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值

    2)  在模块内的 static 全局变量可以被模块内所有函数访问,但不能被模块外其他函数访问

    3)  在模块内的static 函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内

    4)  在类的static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝

    5)  在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的 static 成员变量

11. 头文件种的ifndef/define/endif 是干什么用的

      防止头文件被重复包含

14. 线程和进程

  1) 联系和区别

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

 2)线程的基本概念、线程的基本状态及状态之间的关系?

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

        线程有四种状态:新生状态、可运行状态、被阻塞状态、死亡状态。状态之间的转换如下图所示:

3)多线程有几种实现方法,都是什么?

  1. 继承 Thread 类

  2. 实现 Runnable 接口再 new Thread(YourRunnableOjbect) 

4)多线程同步和互斥有何异同,在什么情况下分别使用他们?举例说明

  线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。

  线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥可以看成是一种特殊的线程同步

5)进程间的通信方式

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

6)线程同步的方式

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

 http://blog.youkuaiyun.com/zsf8701/article/details/7844316

12. TCP和UDP

    1)有什么区别

     TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。

                 当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。

                 TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

     UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。

                 UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。

                 由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快

    2)编写socket套接字的步骤

    3)TCP三次握手和四次挥手, 以及各个状态的作用

13.linux

    1) 使用过的 shell 命令

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

    2)使用过的 vim 命令

      wq!, dd , dw , yy , p , i , %s/old/new/g , /abc 向后搜索字符串abc , ?abc向前搜索字符串abc

14. 海量数据处理的知识点,(hash表, hash统计)

 https://blog.youkuaiyun.com/mbuger/article/details/61916219

15. 什么时候要用虚析构函数

       通过基类的指针来删除派生类的对象时,基类的析构函数应该是虚的。否则其删除效果将无法实现。

       一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,从而千万内存泄漏。

      原因:

              在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。

              如果想要用基类对非继承成员进行操作,则要把基类的这个操作(函数)定义为虚函数。
              那么,析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的。

      注意:

      如果不需要基类对派生类及对象进行操作,则不能定义虚函数(包括虚析构函数),因为这样会增加内存开销。

16. c++怎样让返回对象的函数不调用拷贝构造函数

    拷贝构造函数前加 “explicit” 关键字

17. 大并发( epoll )

       优点:

             http://blog.youkuaiyun.com/sunyurun/article/details/8194979

       实例:

             http://www.cnblogs.com/ggjucheng/archive/2012/01/17/2324974.html



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值