讨论/求职面试/面试题目丨求职学习笔记|InterviewGuide | C++知识点总结(二)/
面试题目丨求职学习笔记|InterviewGuide | C++知识点总结(二)

11、宏定义和typedef区别?

  • 宏主要用于定义常量及书写复杂的内容;typedef主要用于定义类型别名。

  • 宏替换发生在编译阶段之前,属于文本插入替换;typedef是编译的一部分。

  • 宏不检查类型;typedef会检查数据类型。

  • 宏不是语句,不在在最后加分号;typedef是语句,要加分号标识结束。

  • 注意对指针的操作,typedef char * p_char和#define p_char char *区别巨大。

12、变量声明和定义区别?

  • 声明仅仅是把变量的声明的位置及类型提供给编译器,并不分配内存空间;定义要在定义的地方为其分配存储空间。

  • 相同变量可以在多处声明(外部变量extern),但只能在一处定义。

13、哪几种情况必须用到初始化成员列表?

  • 初始化一个const成员。

  • 初始化一个reference成员。

  • 调用一个基类的构造函数,而该函数有一组参数。

  • 调用一个数据成员对象的构造函数,而该函数有一组参数。

14、strlen和sizeof区别?

  • sizeof是运算符,并不是函数,结果在编译时得到而非运行中获得;strlen是字符处理的库函数。

  • sizeof参数可以是任何数据的类型或者数据(sizeof参数不退化);strlen的参数只能是字符指针且结尾是'\0'的字符串。

  • 因为sizeof值在编译时确定,所以不能用来得到动态分配(运行时分配)存储空间的大小。

  int main(int argc, char const *argv[]){
      
      const char* str = "name";

      sizeof(str); // 取的是指针str的长度,是8
      strlen(str); // 取的是这个字符串的长度,不包含结尾的 \0。大小是4
      return 0;
  }

15、常量指针和指针常量区别?

  • 指针常量是一个指针,读成常量的指针,指向一个只读变量。如int const *p或const int *p。

  • 常量指针是一个不能给改变指向的指针。指针是个常量,不能中途改变指向,如int *const p。

    update1:https://www.***r.com/discuss/597948 ,网友“ 牛客191489444号 ”指出笔误,感谢!

16、a和&a有什么区别?

假设数组int a[10];
int (*p)[10] = &a;
  • a是数组名,是数组首元素地址,+1表示地址值加上一个int类型的大小,如果a的值是0x00000001,加1操作后变为0x00000005。*(a + 1) = a[1]。
  • &a是数组的指针,其类型为int (*)[10](就是前面提到的数组指针),其加1时,系统会认为是数组首地址加上整个数组的偏移(10个int型变量),值为数组a尾元素后一个元素的地址。
  • 若(int *)p ,此时输出 *p时,其值为a[0]的值,因为被转为int *类型,解引用时按照int类型大小来读取。

17、数组名和指针(这里为指向数组首元素的指针)区别?

  • 二者均可通过增减偏移量来访问数组中的元素。

  • 数组名不是真正意义上的指针,可以理解为常指针,所以数组名没有自增、自减等操作。

  • 当数组名当做形参传递给调用函数后,就失去了原有特性,退化成一般指针,多了自增、自减操作,但sizeof运算符不能再得到原数组的大小了。

18、野指针和悬空指针

都是是指向无效内存区域(这里的无效指的是"不安全不可控")的指针,访问行为将会导致未定义行为。

  • 野指针
    野指针,指的是没有被初始化过的指针

    int main(void) { 
        
        int* p;     // 未初始化
        std::cout<< *p << std::endl; // 未初始化就被使用
        
        return 0;
    }
    

    因此,为了防止出错,对于指针初始化时都是赋值为 nullptr,这样在使用时编译器就会直接报错,产生非法内存访问。

  • 悬空指针
    悬空指针,指针最初指向的内存已经被释放了的一种指针。

    int main(void) { 
      int * p = nullptr;
    
      int* p2 = new int;
      
      p = p2;
    
      delete p2;
    }
    

    此时 p和p2就是悬空指针,指向的内存已经被释放。继续使用这两个指针,行为不可预料。需要设置为p=p2=nullptr。此时再使用,编译器会直接保错。

    避免野指针比较简单,但悬空指针比较麻烦。c++引入了智能指针,C++智能指针的本质就是避免悬空指针的产生。

产生原因及解决办法:

野指针:指针变量未及时初始化 => 定义指针变量及时初始化,要么置空。

悬空指针:指针free或delete之后没有及时置空 => 释放操作后立即置空。

19、迭代器失效的情况

以vector为例:

插入元素:

1、尾后插入:size < capacity时,首迭代器不失效尾迭代失效(未重新分配空间),size == capacity时,所有迭代器均失效(需要重新分配空间)。

2、中间插入:中间插入:size < capacity时,首迭代器不失效但插入元素之后所有迭代器失效,size == capacity时,所有迭代器均失效。

删除元素:

尾后删除:只有尾迭代失效。

中间删除:删除位置之后所有迭代失效。

deque 和 vector 的情况类似,

而list双向链表每一个节点内存不连续, 删除节点仅当前迭代器失效,erase返回下一个有效迭代器;

map/set等关联容器底层是红黑树删除节点不会影响其他节点的迭代器, 使用递增方法获取下一个迭代器 mmp.erase(iter++);

unordered_(hash) 迭代器意义不大, rehash之后, 迭代器应该也是全部失效.

20、C和C++的区别

  • C++中new和delete是对内存分配的运算符,取代了C中的malloc和free。
  • 标准C++中的字符串类取代了标准C函数库头文件中的字符数组处理函数(C中没有字符串类型)。
  • C++中用来做控制态输入输出的iostream类库替代了标准C中的stdio函数库。
  • C++中的try/catch/throw异常处理机制取代了标准C中的setjmp()和longjmp()函数。
  • 在C++中,允许有相同的函数名,不过它们的参数类型不能完全相同,这样这些函数就可以相互区别开来。而这在C语言中是不允许的。也就是C++可以重载,C语言不允许。
  • C++语言中,允许变量定义语句在程序中的任何地方,只要在是使用它之前就可以;而C语言中,必须要在函数开头部分。而且C++允许重复定义变量,C语言也是做不到这一点的
  • 在C++中,除了值和指针之外,新增了引用。引用型变量是其他变量的一个别名,我们可以认为他们只是名字不相同,其他都是相同的。
  • C++相对与C增加了一些关键字,如:bool、using、dynamic_cast、namespace等等

C语言与C++有什么区别?https://www.cnblogs.com/ITziyuan/p/9487760.html

1

该《InterviewGuide》系列不断连载中,涉及C++、操作系统、计算机网络、数据库(MySql、Redis)、常见智力题等知识点,全部整理内容已在github开源:https://github.com/forthespada/InterviewGuide