C++面试问题整理

静态库与动态库的区别:

  • 静态(函数)库
    • 一般扩展名为(.a或.lib),这类的函数库通常扩展名为libxxx.a或xxx.lib 。
      这类库在编译的时候会直接整合到目标程序中,所以利用静态函数库编译成的文件会比较大,这类函数库最大的优点就是编译成功的可执行文件可以独立运行,而不再需要向外部要求读取函数库的内容;但是从升级难易度来看明显没有优势,如果函数库更新,需要重新编译。
    • 动态函数库
      动态函数库的扩展名一般为(.so或.dll),这类函数库通常名为libxxx.so或xxx.dll 。
      与静态函数库被整个捕捉到程序中不同,动态函数库在编译的时候,在程序里只有一个“指向”的位置而已,也就是说当可执行文件需要使用到函数库的机制时,程序才会去读取函数库来使用;也就是说可执行文件无法单独运行。这样从产品功能升级角度方便升级,只要替换对应动态库即可,不必重新编译整个可执行文件。
  • 总结:综上,不能看出:

    • 从产品化的角度,发布的算法库或功能库尽量使动态库,这样方便更新和升级,不必重新编译整个可执行文件,只需新版本动态库替换掉旧动态库即可。
    • 从函数库集成的角度,若要将发布的所有子库(不止一个)集成为一个动态库向外提供接口,那么就需要将所有子库编译为静态库,这样所有子库就可以全部编译进目标动态库中,由最终的一个集成库向外提供功能。

原博客:https://blog.csdn.net/wonengguwozai/article/details/93195827

C语言代码如何编译:

预处理:预处理过程实质上是处理“#”,将#include包含的头文件直接拷贝到hell.c当中;将#define定义的宏进行替换,同时将代码中没用的注释部分删除等

链接:链接过程使用链接器将该目标文件与其他目标文件、库文件、启动文件等链接起来生成可执行文件。

const在不同的位置对指针的影响

const如果在*a前,那么修饰的就是*a,如果*在const前,那么修饰的就是a。如果有两个const,一个在*之前,一个在*之后,那么*和a都被修饰。const修饰谁,谁就没法改变。

const在*a前:这个指针是可变的,也就是我们可以通过给a赋上不同的地址来改变a指向的内存,也可以用a得到内存中的变量的值。但a指向的内容不能改变,即无法修改*a,也就是指向的变量不能通过*a间接修改。

int p=1;
const int*a;
a= &p;
cout<<*a<<endl;//此时打印1
//*a=1;(编译失败)

*在const前,可以改变*a指向的内容,但不能改变a的值。内存可以通过*a进行修改,但a存储的地址不能被修改,它一经过初始化后就“绑定”在了初始化的地址对应的内存上。也就是指针本身存储的地址变成了一个常量,不能给a赋值来修改指针的指向,*a也就永远代表最初指向的那个变量的值。(指针本身的指向不可变,但是指向的值可以被修改)

指针与引用的区别 

本质区别与性质区别:

  • 指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已
  • 可以有const指针,但是没有const引用;指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)
  • 指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;
  • 指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了。
  • "sizeof引用"得到的是所指向的变量(对象)的大小,而"sizeof指针"得到的是指针本身的大小;

指针与引用作为函数参数传递时的区别:

  • 指针作为函数参数时,也是值传递,只不过是将变量的地址值传递,而引用作为函数参数时实质上传递的是实参本身,即传递进来的不是实参的一个拷贝,因此对形参的修改其实是对实参的修改,所以在用引用进行参数传递时,不仅节约时间,而且可以节约空间。

new与malloc的区别

  • new在动态分配内存的时候可以初始化对象,调用其构造函数,delete在释放内存时调用对象的析构函数。而malloc只分配一段给定大小的内存,并返回该内存首地址指针,如果失败,返回NULL。
  • 申请失败返回:new在申请空间失败后返回的是错误码bad_alloc,malloc在申请空间失败后会返回NULL
  • 属性上:new/delete是C++关键字和操作符需要编译器支持,maollc是库函数,需要添加头文件
  • 参数:new是面向对象的,new在申请内存分配时不需要指定内存块大小,编译器会更具类型计算出大小,malloc需要显示的指定所需内存的大小
  • 成功返回类型:new操作符申请内存成功时,返回的是对象类型的指针,类型严格与对象匹配,无需进行类型转换,因此new是类型安全性操作符。malloc申请内存成功则返回void*,需要强制类型转换为我们所需的类型
  • 有了malloc/free为什么还要new/delete? 

    1) malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。 
    2) 对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。 
    因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。 
    我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。 
    3) 既然new/delete的功能完全覆盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?这是因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。 

STL迭代删除元素

  • 连续内存序列容器(vector,string,deque):序列容器的erase方法返回值是指向紧接在被删除元素之后的元素的有效迭代器,可以根据这个返回值来安全删除元素。
    vector<int> c;
    for(vector<int>::iterator it = c.begin(); it != c.end();)
    {
    if(*it)
      it = c.erase(it);
     else
      ++it; 
    }

     

  • 关联容器(set,multiset,map,multimap):序列容器的erase方法没有返回值,当前的迭代器失效。所以删除前必须确保能得到下一个迭代器

map<string, int> m;
for(map<string, int>::iterator iter=m.begin();iter!=m.end();){
    if(satisfy conditions){
        m.erase(it++);
    }
    else{
        iter++;
    }
}

C++多态是什么

多态是面向对象程序设计的又一重要特性,它指同样的消息被不同类型的对象接受时导致不同行为的现象,不同的行为指函数执行的内容。

多态又分为静态多态与动态多态,静态多态在编译时系统便能确定要调用哪个函数,主要通过函数重载实现

动态多态是指程序在编译时并不能确定要调用的函数,直到运行时系统才能动态地确定操作所针对地具体对象,它又被称作运行时多态。动态多态是通过虚函数实现的。对于同一消息,在运行时对不同地对象产生不同的响应方式。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值