IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> C/C++语言 -> 正文阅读

[移动开发]C/C++语言

目录

C 和 C++ 的区别

指针和引用的区别

malloc 和 new,free 和 delete 的区别

extern C 的作用

常用的容器有哪些

volatile 关键字的作用

有哪几种强制类型转换以及使用场景

c++11 新特性

C++ 20 新特性

C++ 的三大特性

C++的多态实现原理

什么是虚函数

什么是纯虚函数

虚表指针的大小

虚函数表的存放内容

构造函数可以是虚函数吗

析构函数可以是虚函数吗

一个空类会生成哪些函数

左值和右值

什么是智能指针,有哪几种,作用,实现原理

如何避免循环依赖

unique_ptr 中 std::move() 作用

static 关键字的使用

const 关键字的使用

define 和 online 的区别

面向对象的设计原则

C++ 编译过程

函数调用的具体实现


C 和 C++ 的区别

除了面向对象与面向过程这个回答之外,C 与 C++ 的真正区别在哪里?

这几年不管是社团实习工作面试都有被问到这个问题。但是「面向对象以及面向过程」这个回答似乎都不是最好或者最完善的答案。

所以这个问题根本没有简单的答案,选3个角度谈就能写3篇论文。简单说说几个常见的误区。

误区1:C++是面向对象的C?并不是。现代C++是至少四种编程范式的集合体(面向过程,面向对象,泛型编程和元编程,函数式编程等,实际可能不止4种)。说C++是面向对象语言,是一种很瞧不起C++的说法,因为面向对象仅仅是C++的多种范式之一。

误区2:C是面向过程语言?不能这么说。在面向对象方面,C语言提供的语法支持比较薄弱,但这不表示C是面向过程的语言。用C语言写面向对象程序不仅不弱,甚至会有一些优势。世界上有很多非常重要的、大量使用面向对象技术的软件是用纯C写的。例如Linux的图形界面GNOME。

误区3:C是C++的子集,C支持的语法C++都支持。不对。C++在最初设计时是基于C的,绝大多数语法都兼容。但是,在一些细节却重要的地方,二者差别非常大。例如,C语言的函数指针非常神奇:

int (*pfunc)();

看上去pfunc可以指向返回值为int,无参数的函数?并不是。实际上pfunc可以指向任意返回值为int的函数,无论参数是什么。而无参的情况必须写明参数为void:

int (*pfunc)(void);

C语言不必指定参数类型也可以引用函数,这一点让C语言具有很强的动态特性。而C++去除了这种设计,因为破坏了类型安全。同理,C语言常用的(void*)转换在C++中也在很大程度上摒弃了,理由也是类型不安全。哪个设计好哪个不好不重要。重要的是:C并不是C++的子集,C++也不是C的超集。它们在语法、设计理念、常用写法方面均有不同,到今天二者的差别越来越大。

误区4:C++比C功能多,所以C++运行比C慢一点。不对。虽然C++加入了很多很多功能,但由于绝大多数功能都是在编译器上做手脚,大多情况下仅影响编译速度,而不影响运行速度。而且泛型、元编程等技术用好了,能让C++的程序运行的更快。反而是C,由于大量使用不定类型的转换,损失的性能相当可观。

总之,C与C++的区别远不是一段话能够讲清楚。

指针和引用的区别

1) 指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。"sizeof引用"得到的是所指向的变量(对象)的大小,而"sizeof指针"得到的是指针本身的大小;

2) 引用必须被初始化,指针不必。

3) 引用初始化以后不能被改变,指针可以改变所指的对象。

4) 不存在指向空值的引用,但是存在指向空值的指针。

5) 引用的创建和销毁不会调用类的拷贝构造函数和析构函数。

6)?指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)。

malloc 和 new,free 和 delete 的区别

1) new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持。

2)?使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。

3)?new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。

4)?new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。

5)?new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。

6)?C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。

7)?new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。

PS:

?在C++中,内存区分为5个区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区;

?在C中,C内存区分为堆、栈、全局/静态存储区、常量存储区;

extern C 的作用

主要作用就是为了能够正确实现C++代码调用其他C语言代码。被extern "C"修饰的变量和函数是按照C语言方式进行编译和链接的。

由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代码和已经写好的C语言库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。

被extern "C"限定的函数或变量是extern类型的,extern是C/C++语言中表明函数和全局变量的作用范围的关键字,该关键字告诉编译器,其申明的函数和变量可以在本模块或其他模块中使用。

extern对应的关键字是static,static表明变量或者函数只能在本模块中使用,因此,被static修饰的变量或者函数不可能被extern C修饰。

常用的容器有哪些

顺序性容器

1) vector:?是一段连续的内存地址,基于数组实现,其提供了自动内存管理功能(采用了STL普遍的内存管理器allocator),可以动态改变对象长度,提供随机访问。在尾部添加和删除元素的时间是常数的,但在头部或中间就是线性时间。

2) list:?非连续的内存,基于链表实现,属于循环双向链表,目的是实现快速插入和删除,但是随即访问却是比较慢。

3)?forward_list:?实现了单链表,不可反转。相比于list,forward_list更简单,更紧凑,但功能也更少。

4) deque:?双端队列(double-ended queue),支持随机访问,与vector类似,主要区别在于,从deque对象的开始位置插入和删除元素的时间也是常数的,所以若多数操作发生在序列的起始和结尾处,则应考虑使用deque。为实现在deque两端执行插入和删除操作的时间为常数时间这一目的,deque对象的设计比vector更为复杂,因此,尽管二者都提供对元素的随机访问和在序列中部执行线性时间的插入和删除操作,但vector容器执行这些操作时速度更快些。

5) queue:?是一个适配器类,先进先出。queue模板让底层类(默认是deque)展示典型的队列接口。queue模板的限制比deque更多,它不仅不允许随机访问队列元素,甚至不允许遍历队列。与队列相同,只能将元素添加到队尾、从队首删除元素、查看队首和队尾的值、检查元素数目和测试队列是否为空。

6)?priority_queue: 是另一个适配器类,支持的操作与queue相同,但最高优先级元素总是第一个出列。两者之间的主要区别在于,在priority_queue中,最大的元素被移到队首。内部区别在于,默认的底层类是vector。可以修改用于确定哪个元素放到队首的比较方式,方法是提供一个可选的构造函数参数。

7)?stack:?与queue相似,stack也是一个适配器类,它给底层类(默认情况下为vector)提供了典型的栈接口,后进先出。

关联容器:?主要有map和set。map是key-value形式的,set是单值。map和set只能存放唯一的key值,multimap和multiset可以存放多个相同的key值。底层都基于树型结构。

1)?map/multimap:?map容器提供一个键值对(key-value)容器,map与multimap差别仅仅在于multimap允许一个键对应多个值。对于迭代器来说,可以修改实值,而不能修改key。map会根据key自动排序。

2)?set/multiset:?set的含义是集合,它是一个有序的容器,里面的元素都是排序好的支持插入、删除、查找等操作,就像一个集合一样,所有的操作都是严格在logn时间内完成,效率非常高。set和multiset的区别是,set插入的元素不能相同,但是multiset可以相同,set默认是自动排序的,使用方法类似list。

volatile 关键字的作用

volatile指出 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,如在C语言中,volatile关键字可以用来提醒编译器它后面所定义的变量随时有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。

VC++ 在产生release版可执行码时会 进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

1) 并行设备的硬件寄存器(如:状态寄存器)

2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

3) 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。

搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。

有哪几种强制类型转换以及使用场景

1. C风格强制类型转换,如

Type b = (Type)a;

2. C++风格强制类型转换,有static_castconst_castreinterpret_castdynamic_cast四种。

static_cast:?比C风格的强制类型转换要安全很多,有很大程度上的类型安全检查。但结果可能会出错,而且编译器不会给出错误信息。有明显缺点的,那就是无法消除const和volatile属性。

const_cast:?去除掉const或volitale属性。不是用于去除变量的常量性,而是去除指向常量对象的指针或引用的常量性,其去除常量性的对象必须为指针或引用,并且const_cast不支持不同类型指针或引用之间的转换,比如说float*转换成int*是不允许的,相差的话只能差const或volatile属性。

reinterpret_cast:?意为“重新解释”,它是C++中最接近于C风格强制类型转换的一个关键字。它让程序员能够将一种对象类型转换为另一种,不管它们是否相关。可以先使用reinterpret_cast把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值。使用reinterpret_cast强制转换过程仅仅只是比特位的拷贝,和C风格极其相似,实际上reinterpret_cast的出现就是为了让编译器强制接受static_cast不允许的类型转换,因此使用的时候要谨而慎之。

dynamic_cast: 是运行时处理的,运行时会进行类型检查(这点和static_cast差异较大)。不能用于内置基本数据类型的强制转换,只能对指针或引用进行强制转换。如果转换成功的话返回的是指向类的指针或引用,转换失败的话则会返回nullptr。进行上行转换时,与static_cast的效果是完全一样的,进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。而且dynamic_cast运行时的类型检查需要有运行时类型信息,这个信息是存储在类的虚表中的。

c++11 新特性

C++ 20 新特性

C++ 的三大特性

C++的多态实现原理

什么是虚函数

什么是纯虚函数

虚表指针的大小

虚函数表的存放内容

构造函数可以是虚函数吗

析构函数可以是虚函数吗

一个空类会生成哪些函数

左值和右值

什么是智能指针,有哪几种,作用,实现原理

如何避免循环依赖

unique_ptr 中 std::move() 作用

static 关键字的使用

const 关键字的使用

define 和 online 的区别

面向对象的设计原则

C++ 编译过程

函数调用的具体实现

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:39:38  更:2021-09-04 17:41:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:03:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码