C/C++知识点总结1

最近想对c/c++方面的知识点进行复习,因此在接下来的几天会把之前整理好的知识点按照文字解释和代码实现等更新到csdn中,若是存在错误或是不当的地方,请看到的朋友批评指正。

1.c和c++的区别:

c是一种结构化和流程话的语言,更偏重于底层和算法,而c++是在c语言的基础上引入了类、对象的概念,对现实进行抽象和解释

2.const的主要作用:

a)修饰变量表示只读(注:此处不应该说是常量,而应该说是只读变量),初始化的时候只能通过初始化列表

b)修饰函数参数只读,防止在函数内部被修改

c)修饰函数体,证明此函数是成员函数,反之普通函数不能用const。const函数只能调用const函数,非const函数可以调用const函数(注:此时表示不修改成员变量的值)

3.指针和引用的区别:

关于指针和引用无论是面试还是平时的工作,大概分为一下几种:

a)前者可以为空、后者不可以

b)指针只是一个变量,只不过这个变量存储的是一个地址。而引用是变量的别名

c)引用只能在初始化的时候被赋值,而指针随时都可以

d)引用变量内存单元保存的是引用变量的内存地址,从内存分配上,程序为指针变量分配内存区域,而引用变量则不需要分配内存区域

e)sizeof大小:引用则是指向变量的大小,而指针则是指向指针本身的大小

f)指针可以有多级,但是引用只能有一级

g)指针可以有const,但是引用则没有

h)引用在源代码中相当于普通变量,但是在函数中作为参数时,内部传递的实际上是变量地址

注:引用的内部实现其实是只读指针,存放的是变量的地址

注:函数传值、传引用、传指针区别
传值:传值无非就是实参拷贝传递给形参,单向传递(实参->形参),赋值完毕后实参就和形参没有任何联系,对形参的修改就不会影响到实参。
传指针:传指针是把实参地址的拷贝传递给形参。还是一句话,传指针就是把实参的地址复制给形参。复制完毕后实参的地址和形参的地址没有任何联系,对实参形参地址的修改不会影响到实参, 但是对形参地址所指向对象的修改却直接反应在实参中,因为形参指向的对象就是形参的对象。
传引用:传引用本质没有任何实参的拷贝,一句话,就是让另外一个变量也执行该实参。就是两个变量指向同一个对象。这是对形参的修改,必然反映到实参上。

4.多态的实现:

对于学习c++的朋友来说多态肯定不是一个陌生的词汇,但是多态其实分为两种,动多态和静多态

静多态:通常指的是诸如:宏替换、函数模板之类的

动多态:就是我们都知道的通过子类对父类同名虚函数的重写来实现的多态

5.内存五大区:

堆区、栈区、全局区(静态区)、常量存储区、程序代码区(注:也有的说是自由存储区)

6.堆和栈的区别:

栈:在编译器需要时自动分配的,不需要时自动清除的变量存储区。通常存放局部变量和函数参数等。

堆:由程序员手动分配和回收,若未能及时回收则会在程序结束时由系统回收

7.static的作用和用法:

static修饰的变量或者函数表示静态变量或者静态函数,其作用域取决于其定义位置,定义在类的成员变量中,则被类的所有对象所用,定义在函数中则被函数内的成员所用,如果作为static 的局部变量它的生命周期是整个源程序,但是必须在定义该变量的函数中使用才有效,退出该函数,最然变量仍存在,但是不可用。

因为静态函数没有this指针,所以只能用类名加上作用域来调用静态方法   因此可以利用这一特性来实现函数的隐藏,即:此时若存在普通函数的名字与静态函数重名也不会出现问题

static修饰的变量在程序开始运行时就完成了初始化,也是唯一一次初始化

static默认初始化为0

注:因为没有this指针,所以在静态函数中不可以调用普通函数,而在普通函数中可以通过类名和作用域来调用静态函数

8.关于拷贝构造的一些理解:

拷贝构造的调用时机在我看来分为如下三种情况:

a)当对象作为参数要进行传递时

b)当对象作为返回值,以值传递的方式从函数返回

c)当用一个对象赋值给另一个对象的时候

当调用拷贝构造的时候会产生两种情况,深拷贝和浅拷贝。二者的区别就是是否拷贝地址

注:若是成员变量存在指针,而在拷贝的时候没有开辟新的空间,而是两个对象共用一个成员变量的地址,此时就是浅拷贝,容易出现问题。因此,在成员变量存在指针而对象之间又要产生赋值操作时,应该考虑深拷贝,即:在拷贝构造函数中为指针变量开辟新的空间之后再赋值。

9.面向过程和面向对象的区别:

面向过程-步骤化:面向过程就是分析出实现需求所需要的步骤、通过函数逐步去实现这些步骤,一次调用即可

面向对象-行为化:面向对象是吧整个需求按照特点、功能来进行划分和封装,创建了类对象不是为了完成某一个步骤,而是描述某个事物(对象)在解决问题中的行为

10.构造函数是否可以试虚函数:

看到这个问题大家潜意识肯定是不可以,但是原因呢,让我们一起分析一下。

虚函数在于通过子类的指针或是引用来调用父类的方法,并予以重写。而构造函数是创建对象时去自动调用的方法,不可能通过子类的指针再去调用。另外网络上还有一个普遍的解释方法,虚函数的实现要通过虚表“vtable”,但是“vtable”是存在于对象的存储空间,而想要构建对象则需要构造函数,而假设构造函数是虚函数就必须调用“vtable”,但是此时对象还未实例化,自然也就不存在“vtable”,因此陷入了死循环之中

11.构造函数可以调用虚函数吗:

不可以。当此构造函数作为基类时,构造子类对象中的父类属性时,必然会触发父类虚函数,而此时就是相当于调用一个未完全初始化的对象,后果不可测,很危险。

12.RAII技术:

RAII技术指的是资源的自动管理,比如内存管理。。其中智能指针就是典型代表,由开发人员申请空间,但是不用考虑释放空间,而是由智能指针自己去释放就好。

13.c语言和c++的链接库可以相互调用吗:

答案是可以的。利用关键字extern “c”即可以在c++程序中调用c语言的链接库。

而在c++程序中,在cpp文件中的每个函数定义都加上extern “c”前缀,既可以编译成c语言可以链接的库。

14.main函数没有返回值可以吗:

可以,但是不好。因为有返回值表示程序正常退出,没有返回值表示程序非正常退出,因此还是建议加上返回值。

注1:main函数的参数用法及意义:argc 是 argument count的缩写,表示传入main函数的参数个数;
argv 是 argument vector的缩写,表示传入main函数的参数序列或指针,并且第一个参数argv[0]一定是程序的名称,并且包含了程序所在的完整路径,所以确切的说需要我们输入的main函数的参数个数应该是argc-1个;

注2:main虽说是主函数,程序的入口,但是并不是最先执行的,在此之前还包括如:编译、链接、宏的替换、静态变量的初始化等等。

15.异常捕获:

try{}

catch()

{}

注:此种异常捕获,默认只对debug模式下管用,若是release版本的话则需要进行一下配置。项目--->xxx属性--->配置属性--->C/C++   --->命令行,在“附加选项”中输入:/EHa,然后确定即可。    

16.左值与右值的定义:(c++11move的用法,右值引用)

左值与右值的定义来自于c语言,左值指的是既可以放在等号左边也可以放在等号右边的变量或表达式,右值指的是只能放置在等号右边的变量或表达式

17.c语言从源代码到二进制可执行文件需要经历几部分:

编译(预处理、编译、汇编)和链接

预处理:包括宏的替换,#include文件的解析 #using命令的处理等

编译:将预处理的文件进行词法的解析、语法分析、语义分析及优化

汇编:将编译完的文件翻译成机器指令,并生成可重定位的文件,该文件是二进制文件,字节编码是机器指令

18.sizeof与strlen的区别

前者是运算符,编译的时候就已经计算好了,其计算的大小是能容纳对象的最大容量的字节大小

后者是函数,计算的是字符串的实际长度,不包括“\0”

19.虚函数表会随着对象的生成而复制一份吗??

(我自己的理解,在网上没有直接找到答案)虚函数表归属于类,不属于对象。类的所有对象共享类的虚函数表。并且我个人理解:子类对象与指向子类指针的基类指针指向的对象共享一个同一个虚函数表,符合c++的多态原则

20.c++特性:封装、继承、多态

c++的好处:可维护性、可扩充性、可复用性

21.c++中有了malloc/free方法,为什么还要引入new/delete操作符:

前者是标准库函数,后者是操作符。都可以用于动态的申请内存和释放内存

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

22.为什么要用到虚析构:

当需要利用基类指针对子类对象做操作的时候。即:利用基类指针删除子类对象的时候

23.怎样让返回对象的函数不调用拷贝构造函数:

拷贝构造函数前加 “explicit” 关键字;这样拷贝构造函数就不会进行自动类型转换,也就不会实现拷贝构造函数的调用了。
explicit主要是用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。

24.函数模板的底层实现:

函数模板其实是两次编译,在声明的地方对函数模板进行编译,在调用的地方对模板进行替换后再次进行编译

25.可继承的类应该包含哪些内容:

1.析构函数应该是虚的,允许父类指针删除子类对象(即:调用子类析构)防止造成内存泄漏

注:子类会显示的调用父类的构造函数,若没有则会调用默认构造函数,若是再没有则会报错

26.c++类的基本构成:

默认构造、有参构造、拷贝构造、析构函数、运算符重载

27.如何用c语言模仿c++的多态:

可以考虑用struct,但是结构体中没有成员函数,可以考虑用函数指针。

28.override重写关键字 明确告诉编译器此方法是重写基类方法 若基类不存在则会报错

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值