C++ 面试考点(二)

点击蓝字

ddca9f72ea780f16d34692f17d3f0e8a.png

关注我们

11、`extern` 用法?

  • extern 修饰变量的声明

    • 如果文件`a.c` 需要引用`b.c` 中变量`int v`,就可以在`a.c` 中声明`extern int v`,然后就可以引用变量`v`。

  • extern 修饰函数的声明

    • 如果文件`a.c` 需要引用`b.c` 中的函数,比如在`b.c` 中原型是`int fun(int mu)`,那么就可以在`a.c` 中声明`extern int fun(int mu)`,然后就能使用`fun` 来做任何事情。

    • 就像变量的声明一样,`extern int fun(int mu)`可以放在`a.c` 中任何地方,而不一定非要放在`a.c` 的文件作用域的范围中。

    • 默认情况情况下函数都是`extern`的, 除非使用`static`对函数进行了隐匿

  • extern 修饰符可用于指示C 或者C++函数的调用规范。

    • 比如在`C++`中调用`C` 库函数,就需要在`C++`程序中用`extern “C”`声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用`C` 函数规范来链接。主要原因是`C++`和`C` 程序编译完成后在目标代码中命名规则不同。

12、`int` 转字符串, 字符串转`int`

  • C++11 标准增加了全局函数std::to_string

  • 可以使用std::stoi/std::stol/std::stoll 等等函数

12.1 `strcat`,`strcpy`,`strncpy`,`memset`,`memcpy` 的内部实现?

  • strcatchar *strcat(char *dst, char const *src);

    • 首先找到dstend

    • src的作为结束标志, 将src添加到dstend

    • dst必须有足够的空间保存整个字符串

    • dstsrc都必须是一个由结尾的字符串(空字符串也行)

    • dstsrc内存不能发生重叠

    • 头文件: #include

    • 作用: 将dstsrc字符串拼接起来保存在dst

    • 注意事项:

    • 函数实现:

    • Code

      char *strcat (char * dst, const char * src){assert(NULL != dst && NULL != src);   // 源码里没有断言检测char * cp = dst;while(*cp )cp++;                      /* find end of dst */while(*cp++ = *src++) ;         /* Copy src to end of dst */return( dst );                  /* return dst */}
  • strcpychar *strcpy(char *dst, const char *src);

    • src必须有结束符(), 结束符也会被复制

    • srcdst不能有内存重叠

    • dst必须有足够的内存

    • 头文件:#include

    • 作用: 将src的字符串复制到dst字符串内

    • 注意事项:

    • 函数实现:

      char *strcpy(char *dst, const char *src){   // 实现src到dst的复制if(dst == src) return dst;              //源码中没有此项assert((dst != NULL) && (src != NULL)); //源码没有此项检查,判断参数src和dst的有效性char *cp = dst;                         //保存目标字符串的首地址while (*cp++ = *src++);                 //把src字符串的内容复制到dst下return dst;}
  • strncpychar *strncpy(char *dst, char const *src, size_t len);

    • strncpy 把源字符串的字符复制到目标数组,它总是正好向 dst 写入 len 个字符。

    • 如果 strlen(src) 的值小于 lendst 数组就用额外的 NULL 字节填充到 len 长度。

    • 如果 strlen(src)的值大于或等于 len,那么只有 len 个字符被复制到dst中。这里需要注意它的结果将不会以NULL字节结尾。

    • 头文件: #include

    • 作用: 从src中复制len个字符到dst中, 如果不足len则用NULL填充, 如果src超过len, 则dst将不会以NULL结尾

    • 注意事项:

    • 函数实现:

      char *strncpy(char *dst, const char *src, size_t len){assert(dst != NULL && src != NULL);     //源码没有此项char *cp = dst;while (len-- > 0 && *src != '\0')*cp++ = *src++;*cp = '\0';                             //源码没有此项return dst;}
  • memsetvoid *memset(void *a, int ch, size_t length);

    • 将参数a所指的内存区域前length个字节以参数ch填入,然后返回指向a的指针。

    • 在编写程序的时候,若需要将某一数组作初始化,memset()会很方便。

    • 一定要保证a有这么多字节

    • 头文件: #include

    • 作用:

    • 函数实现:

      void *memset(void *a, int ch, size_t length){assert(a != NULL);     void *s = a;     while (length--)     {     *(char *)s = (char) ch;     s = (char *)s + 1;     }     return a;     }
  • memcpy

    • 从 src 所指的内存地址的起始位置开始,拷贝n个字节的数据到 dest 所指的内存地址的起始位置。

    • 可以用这种方法复制任何类型的值,

    • 如果`src`和`dst`以任何形式出现了重叠,它的结果将是未定义的。

    • 头文件: #include

    • 作用:

    • 函数实现:

      void *memcpy(void *dst, const void *src, size_t length){assert((dst != NULL) && (src != NULL));char *tempSrc= (char *)src;            //保存src首地址char *tempDst = (char *)dst;           //保存dst首地址while(length-- > 0)                    //循环length次,复制src的值到dst中*tempDst++ = *tempSrc++ ;return dst;}

  • strcpy 和 memcpy 的主要区别:

    • 复制的内容不同: `strcpy` 只能复制字符串,而 `memcpy` 可以复制任意内容,例如字符数组、整型、结构体、类等。

    • 复制的方法不同: `strcpy` 不需要指定长度,它遇到被复制字符的串结束符``才结束,所以容易溢出。`memcpy` 则是根据其第`3`个参数决定复制的长度,遇到``并不结束。

    • 用途不同: 通常在复制字符串时用 `strcpy`,而需要复制其他类型数据时则一般用 `memcpy`


  • 参考: 各种C语言处理函数 strcat,strcpy,strncpy,memset,memcpy 总结 - New World - CSDN博客

13、深拷贝与浅拷贝?

  • 浅复制:

    • 只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,

    • 换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。

  • 深复制: 在计算机中开辟了一块新的内存地址用于存放复制的对象


  • 浅复制的问题:

    • 在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。

    • 这时,如果B 中有一个成员变量指针已经申请了内存,那A 中的那个成员变量也指向同一块内存。

    • 这就出现了问题:当B把内存释放了(如:析构),这时A 内的指针就是野指针了,出现运行错误。


14、`C++`模板是什么,底层怎么实现的?

  • 编译器并不是把函数模板处理成能够处理任意类的函数;编译器从函数模板通过具体类型产生不同的函数;

  • 编译器会对函数模板进行两次编译:

    • 在声明的地方对模板代码本身进行编译,

    • 在调用的地方对参数替换后的代码进行编译。

  • 这是因为函数模板要被实例化后才能成为真正的函数,在使用函数模板的源文件中包含函数模板的头文件,如果该头文件中只有声明,没有定义,那编译器无法实例化该模板,最终导致链接错误。

  • 模板可以重载返回值, 函数重载不行


  • 如果我们试图通过在头文件中定义函数模板, 在cpp文件中实现函数模板, 那么我们必须在在实现的那个cpp文件中手动实例化, 也就是使用你需要使用的参数替换模板, 从而使得编译器为你编译生成相应参数的模板函数.


15、`C` 语言`struct` 和`C++` `struct` 区别

  • struct 在C语言中:

    • 用户自定义数据类型`(UDT)`

    • 只能是一些变量的集合体, 成员不能为函数

    • 没有权限设置

    • 一个结构标记声明后,在`C`中必须在结构标记前加上`struct`,才能做结构类型名;


  • struct 在C++中:

    • 抽象数据类型`(ADT)`,支持成员函数的定义,(能继承,能实现多态)。

    • 增加了访问权限, 默认访问限定符为`public`(为了与`C` 兼容),`class` 中的默认访问限定符为`private`

    • 定义完成之后, 可以直接使用结构体名字作为结构类型名

    • 可以使用模板


16、虚函数可以声明为`inline`吗?

  • 虚函数要求在运行时进行类型确定,而内敛函数要求在编译期完成相关的函数替换, 所以不能


  • 虚函数用于实现运行时的多态,或者称为晚绑定或动态绑定。

  • 内联函数用于提高效率, 对于程序中需要频繁使用和调用的小函数非常有用。它是在编译期间,对调用内联函数的地方的代码替换成函数代码。


17、类成员初始化方式?构造函数的执行顺序?为什么用成员初始化列表会快一些?

  • 概念

    • 赋值初始化,通过在函数体内进行赋值初始化;

    • 列表初始化,在冒号后使用初始化列表进行初始化。

  • 这两种方式的主要区别在于:

    • 对于在函数体中初始化,是在所有的成员函数分配空间后才进行的。对于类对象类型成员变量, 则是先调用零参数构造函数, 如果零参数构造函数不存在编译器将会报错.

    • 列表初始化是给数据成员分配内存空间时就进行初始化,就是说分配一个数据成员只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式)。

  • 快的原因: 所以对于列表初始化: 只进行了一次初始化操作, 而赋值初始化则先进性了一次初始化,然后调用了一次复制构造函数.

  • 一个派生类构造函数的执行顺序如下:

    • 虚基类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)。

    • 基类的构造函数(多个普通基类也按照继承的顺序执行构造函数)。

    • 类类型的成员对象的构造函数(按照初始化顺序)

    • 派生类自己的构造函数

18、成员列表初始化?

  • 必须使用成员初始化的四种情况

    • 当初始化一个引用成员时;

    • 当初始化一个常量成员时;

    • 基类, 无零参数构造函数

    • 成员类, 无零参数构造函数

  • 成员初始化列表做了什么

    • 编译器在调用用户代码之前, 会按照类成员声明顺序一一初始化成员变量, 如果成员初始化类别中有初值,则使用初值构造成员函数.

    • 初始化顺序由类中的成员声明顺序决定的,不是由初始化列表的顺序决定的;

19、构造函数为什么不能为虚函数?析构函数为什么要虚函数?

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

  • 首先是没必要使用虚函数:

    • 由于使用间接调用(通过引用或则指针)导致类类型不可信, 而使用虚函数机制完成正确的函数调用.

    • 但是构造函数本身是为了初始化对象实例, 创建对象必须制定它的类型, 其类类型是明确的, 因此在编译期间即可确定调用函数入口地址

    • 因而没必要使用虚函数, 其调用在编译时由编译器已经确定.

  • 其次不能使用虚函数:

    • 虚函数的调用依赖于虚函数表, 虚函数表储存于静态储存区, 在存在虚函数的对象中都将插入一个指向虚函数表的指针,

    • 在对象中插入一个指向虚函数表的指针是由构造函数完成的, 也就是说在调用构造函数时并没有指向虚函数表的指针, 也就不能完成虚函数的调用.

析构函数为什么要虚函数?

  • C++中基类采用virtual 虚析构函数是为了防止内存泄漏。

    • 如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。

    • 假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。

    • 所以,为了防止这种情况的发生,`C++`中基类的析构函数应采用`virtual` 虚析构函数。

20、析构函数的作用,如何起作用?

  • 析构函数名与类名相同,只是在函数名前增加了取反符号~以区别于构造函数,其不带任何参数, 也没有返回值. 也不允许重载.

  • 析构函数与构造函数的作用相反, 当对象生命周期结束的时候,如对象所在函数被调用完毕时,析构函数负责结束对象的生命周期. 注意如果类对象中分配了堆内存一定要在析构函数中进行释放.

  • 和拷贝构造函数类似,如果用户未定义析构函数, 编译器并不是一定会自动合成析构函数, 只有在成员变量或则基类拥有析构函数的情况下它才会自动合成析构函数.

  • 如果成员变量或则基类拥有析构函数, 则编译器一定会合成析构函数, 负责调用成员变量或则基类的析构函数, 此时如果用户提供了析构函数,则编译器会在用户析构函数之后添加上述代码.

  • 类析构的顺序为: 派生类析构函数, 对象成员析构函数, 基类析构函数.

*声明:本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

2f88697fa262671f31fa96abedecb411.png

386a194e0d65d05144848e2c46c3fa2e.gif

戳“阅读原文”我们一起进步

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337676.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内存不能为read进不去桌面_四级报名进不去怎么办

英语四级报名进不去怎么办?这里提供有两种方法,一种是重复刷新,直到页面出现;另外一种就是错峰报名,叉开登录高峰期。很多考生在报名的时候遇到困难,最多的就是报名页面进不去,这个时候有一些考生就会产生疑惑&#x…

C语言线程库的使用,这篇值得收藏!

点击蓝字关注我们1. 线程概述线程是轻量级的进程(LWP:light weight process),在 Linux 环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合,指令按照既定的逻辑控制计算机运行。操作系统会以进…

alexeyab darknet 编译_【目标检测实战】Darknet—yolov3模型训练(VOC数据集)

原文发表在:语雀文档0.前言本文为Darknet框架下,利用官方VOC数据集的yolov3模型训练,训练环境为:Ubuntu18.04下的GPU训练,cuda版本10.0;cudnn版本7.6.5。经过一晚上的训练,模型20个类别的mAP达到…

html字符串转svg,【SVG】如何操作SVG Text

上周我们学习了如何使用元素创建SVG文本。在实例中我们设置了x和y坐标来定位文本,也尝试了给SVG文本中的每个字符定位。关于元素还有很多内容。在处理SVG文本时,不要局限于x和y属性。元素还有几个可以添加的属性,现在我们开始讨论吧。dx和dy属…

C++ 面试考点(三)

点击蓝字关注我们21、构造函数和析构函数可以调用虚函数吗,为什么在C中,提倡不在构造函数和析构函数中调用虚函数;在构造函数和析构函数调用的所有函数(包括虚函数)都是编译时确定的, 虚函数将运行该类中的版本.因为父类对象会在子类之前进行…

用终端访问路由器设置端口开发_serial for mac(终端管理软件)v2.0.3

原标题:serial for mac(终端管理软件)v2.0.3serial for mac是应用在Mac上的一款终端管理软件,可以帮助您连接和控制串行设备,如服务器,路由器或调制解调器等网络设备,PBX系统等。好消息是Serial为大多数串行设备提供了…

大神级的C++性能优化,你能看懂吗?

点击蓝字关注我们一、前言性能优化不管是从方法论还是从实践上都有很多东西,文章会从C语言本身入手,介绍一些性能优化的方法,希望能做到简洁实用。二、实例1在开始本文的内容之前,让我们看段小程序:// 获取一个整数对应…

钢笔墨水能否代替打印机墨水_LAMY钢笔应该如何选择墨水?

其实墨水世面上基本是有两种:碳素墨水和非碳素。碳素墨水相对比较堵笔,碳素墨水对钢笔本身腐蚀性不大,腐蚀性大的那是染料/颜料墨水。碳素墨水写字非常容易有笔锋,而非碳素墨水就显得略微柔和了。有人说,字写得好的人用…

html ctf查找,Web CTF 解题思路总结—南京邮电大学攻防平台writeup

1、直接查看源代码例:签到题(50)2、PHP的特性(1)MD5 碰撞例:md5 collision(50)md5碰撞:MD5摘要算法可以从多个字节组成的串中计算出由32个字节构成的“特征串”,对于超过32字节的串来说,MD5计算得出的值必然是其一个子…

java 1.8新增功能_睡觉时:新增的Java 8新增功能

java 1.8新增功能自Java 8推出以来,最有趣的功能是什么? Java 8最近庆祝了它的第一个生日,其主要版本已经在一年多以前了。 这当然值得庆祝。 自从最初的Java 8版本问世以来,已经发布了六个更新。 这些更新中的某些元素是次要的…

C++ 为什么不加入垃圾回收机制

点击蓝字关注我们Java的爱好者们经常批评C中没有提供与Java类似的垃圾回收(Gabage Collector)机制(这很正常,正如C的爱好者有时也攻击Java没有这个没有那个,或者这个不行那个不够好),导致C中对动态存储的官吏称为程序员的噩梦,不是…

c++ 共享内存_Python3.8多进程之共享内存

最近发了个宏愿想写一个做企业金融研究的Python框架。拖出Python一看已经更新到了3.8,于是就发现了Python 3.8里新出现的模块:multiprocessing.shared_memory。随手写了个测试。生成一个240MB大小的pandas.DataFrame,然后转换成numpy.recarra…

计算机主机箱外部介绍图,电脑的主机结构是怎样的 电脑主机结构图【图文】...

在电脑已经普及的今天,基本上每家每户都有电脑了,大家用它来看电影,搜索资料啊,上网啊等等。在我们日常的娱乐方式中,电脑也是我们的娱乐项目之一,至少还是好多人用它看电影和追剧的。但是机器会有故障的时…

C 语言各数据类型的内存映像

点击蓝字关注我们C语言各种数据类型的内存映像&#xff08;32位平台&#xff09;&#xff1a;0 signed char#include <stdio.h> int main() {char min 1<<7;char max (1<<7)-1;for(int imin;i<max;i)if(i<0)printf("%.2X ",(unsigned char…

用java编写一个图书管理系统_手把手教你编写第一个java程序

安装完jdk后我们就可以试着编写第一个java程序了&#xff0c;让我们一起来试试吧&#xff01;第一步点击开始——所有程序——附件——记事本&#xff0c;新建记事本&#xff0c;输入以下代码&#xff1a;class HelloWorld { public static void main(String args[]) { System.…

go micro java_Java Micro Framework:您无法忽略的新趋势

go micro java什么是Java微框架&#xff0c;为什么要使用它们&#xff1f; 每种语言都有权衡。 对于Java&#xff0c;要成为一种安全&#xff0c;经过严格测试&#xff0c;向后兼容的语言&#xff0c;就要在敏捷性和简化方面做出一些牺牲。 无可否认&#xff0c;有些冗长和冗长…

C语言调用C++类成员函数讲解和实例

点击蓝字关注我们1、问题成因C语言与C调用问题原因主要在于C编译器和C编译器的不同。C是过程式语言&#xff0c;C编译器编译后&#xff0c;函数在符号库中就是函数名&#xff0c;没有其他任何附加信息。而C是对象式语言&#xff0c;支持函数重载&#xff0c;C编译器编译后&…

学生命科学要学计算机吗,现在学生物学出路真的有那么不济吗?

最近浏览知乎&#xff0c;看到大规模的生物劝退贴&#xff0c;这些帖子纷纷拿出多个例子&#xff0c;并现身说法&#xff0c;告诫学生物的同学尽早转行&#xff0c;并声称劝退一人胜发7篇CNS。作为网友盛传的天坑之首&#xff0c;生物专业到底有多坑&#xff1f;环球科学曾对北…

java笔试题_Java面试才到笔试就没有然后了?快来签收,高频笔试57题及解答

前言很多人面试之前&#xff0c;可能没有在互联网公司工作过或者说工作过但年头较短&#xff0c;不知道互联网公司技术面试都会问哪些问题&#xff1f; 再加上可能自己准备也不充分&#xff0c;去面试没几个回合就被面试官几个问题打蒙了&#xff0c;甚至笔试都过不了。最后以惨…

java开发错误_每个Java开发人员都必须避免的9个安全错误

java开发错误Checkmarx CxSAST是功能强大的源代码分析&#xff08;SCA&#xff09;解决方案&#xff0c;旨在从根本上识别&#xff0c;跟踪和修复技术和逻辑安全漏洞&#xff1a;源代码。 在这里查看 &#xff01; 自从1995年中期引入Java以来​​&#xff0c;它已经走了很长一…