(嵌入式八股)第2章 C++(一)

2.1 C和C++区别(有了C语言为什么还要C++?)

C语言是面向过程语言,而C++是面向对象语言。

编程范式

  • C 语言(面向过程编程):
  • 面向过程编程(Procedure-Oriented Programming)是一种基于函数的编程方式,程序被视为一个由数据和操作数据的函数组成的集合。开发人员通过编写多个函数来完成程序任务,然后按照步骤(流程)依次调用这些函数。
  • 在 C 语言中,开发者必须通过明确的函数调用来控制程序的执行流,数据和函数是分离的,函数操作的是数据,代码的结构主要是围绕函数展开的。

  • C++ 语言(面向对象编程)
  • 面向对象编程(Object-Oriented Programming, OOP)是一种更高层次的编程范式,它将程序组织为对象的集合。每个对象是数据和操作这些数据的函数的结合体。通过创建类和对象,面向对象编程强调数据的封装、继承、多态和抽象。
  • 在 C++ 中,程序不仅仅是函数的集合,而是由具有属性和方法的对象组成。对象和类的概念使得程序设计更符合实际世界的模拟。

数据和函数的关系

  • C 语言:数据和操作数据的函数是分离的。在 C 语言中,数据和函数是独立的,数据由全局或局部变量存储,函数通过参数传递数据进行操作。
  • C++ 语言:数据和操作数据的函数被封装在一起。C++ 引入了类的概念,类不仅包含数据成员(属性),还包含操作这些数据的成员函数(方法)。类提供了一种自然的方式来组织和操作数据。

面向对象的特性(封装、继承、多态)

  • C 语言:C 语言不支持面向对象的特性。它只是一个过程化的语言,无法直接支持类和对象的创建、继承、方法重写等功能。
  • C++ 语言:C++ 支持面向对象编程,并且引入了类、对象、继承、多态等重要特性。封装:类把数据和操作数据的函数封装在一起,提供良好的数据保护。继承:类可以继承其他类的特性和行为,促进代码的复用。多态:通过虚函数和动态绑定,C++ 实现了运行时多态,使得不同类型的对象可以以统一的接口进行操作。

内存管理

  • C 语言:C 语言使用 malloc() 和 free() 函数来进行动态内存管理,手动分配和释放内存,容易出错,如内存泄漏和访问无效内存。
  • C++ 语言:C++ 引入了 new 和 delete 运算符来进行内存的动态分配和释放。new 和 delete 提供了更简单的语法,同时也支持对象的构造和析构。C++ 的内存管理可以通过类的构造函数和析构函数来自动处理资源的分配和释放。

函数重载与运算符重载

  • C 语言:C 语言不支持函数重载,也不支持运算符重载。在 C 中,如果你需要多个具有相似功能的函数,它们的名字必须不同,且类型必须明确指定。
  • C++ 语言:C++ 支持函数重载(同名不同参数的多个函数)和运算符重载(自定义运算符的行为)。这使得 C++ 具有更高的灵活性和扩展性。

示例(函数重载):

  • 函数重载允许我们定义多个相同名字的函数,但每个函数的参数类型或数量必须不同。编译器根据传递的参数类型来决定调用哪个版本的函数。
  • 在上述代码中,print 函数通过接受不同类型的参数(整数、浮点数和字符串)实现了重载。通过这种方式,我们可以利用相同的函数名执行不同类型的打印操作,增强了代码的可读性和可维护性。
  • 标准库

    • C 语言:C 标准库提供了基本的输入输出、字符串操作、内存管理、数学等功能,如 stdio.h、stdlib.h 等头文件。
    • C++ 语言:C++ 标准库不仅包含了 C 语言的标准库,还引入了如标准模板库(STL)等强大的工具。STL 提供了如容器(vector、list)、算法(sort、find)等常用的类和函数,使得 C++ 更加高效和灵活。

    总结

    总体来说,C++ 是在 C 的基础上引入了面向对象编程的特性,同时保留了 C 的面向过程的特性,这使得 C++ 既可以进行高效的系统编程,也可以进行灵活的面向对象设计。

    2.2 new和malloc的区别

    在 C++ 中,new 和在 C 语言中的 malloc 都用于动态内存分配,但它们的原理、用法以及其他方面有一些显著的不同。

    定义与原理

    • new:
    • new 是 C++ 的关键字,用于动态分配内存并创建对象。
    • 它不仅分配内存,还会自动计算所需内存空间,并调用对象的构造函数进行初始化。
    • 使用 new 分配内存时,内存块的类型已经确定,因此无需手动指定内存大小。
    • 分配的内存可以是基本数据类型的内存,也可以是对象的内存。
    • 当使用 new 分配内存时,必须使用 delete 来释放内存,否则会造成内存泄漏。
    • malloc:
    • malloc 是 C 语言的库函数,用于动态分配一块指定大小的内存块。
    • malloc 只分配内存,不会初始化内存的内容,返回的是 void* 类型指针,需要手动强制类型转换。
    • malloc 只关心内存的大小,并不关心内存所存储的数据类型。
    • 返回的内存块是未初始化的。
    • 使用 malloc 分配的内存必须通过 free 来释放,防止内存泄漏。

    语法

    • new 语法:

    • malloc 语法:

    类型安全

    • new:new 是类型安全的,编译器根据数据类型自动计算所需内存空间,并返回对应类型的指针。不需要手动指定内存的大小,且返回的是已指定类型的指针。
    • malloc:malloc 返回的是 void* 类型指针,这意味着它不具备类型信息,因此必须手动进行类型转换。如果直接在 C++ 中使用 malloc,需要强制转换返回的 void* 指针为正确类型。
    • 示例(malloc 使用)

      构造函数与析构函数的调用

    • new:new 会自动调用对象的构造函数来初始化对象,因此创建的对象是已初始化的。对象销毁时会调用析构函数,释放资源。
    • malloc:malloc 不会调用构造函数。它只是为数据分配内存,分配的内存是未初始化的。对象的构造和析构需要手动处理。

    示例(构造函数与析构函数的调用):

  • 构造函数MyClass() 是一个默认构造函数,当对象创建时被调用。它打印 Constructor called! 来表明对象的构造过程。
  • 析构函数~MyClass() 是析构函数,当对象销毁时被自动调用。它打印 Destructor called! 来表示对象的销毁过程。
  • MyClass* obj = new MyClass();:这行代码使用 new 操作符来创建 MyClass 类型的对象 objnew 不仅分配内存,还调用 MyClass 的构造函数初始化对象。
  • delete obj;:这行代码使用 delete 操作符来销毁对象 obj,并自动调用析构函数,释放该对象占用的内存。
  • 内存分配失败的处理

    • new:当 new 分配内存失败时,它会抛出一个 std::bad_alloc 异常。因此,可以通过异常处理来捕获内存分配失败的情况。
    • malloc:当 malloc 分配内存失败时,它会返回 NULL,需要程序员手动检查返回值,确保内存分配成功。

    示例(malloc 内存分配失败处理):

    重载与自定义类型

    • new:
    • new 可以被重载,允许开发者自定义内存分配行为。例如,可以重载 new 操作符来定制内存池管理。
    • new 也能够与自定义类型的构造函数和析构函数配合使用。
    • malloc:
    • malloc 是 C 标准库中的函数,不能被重载。
    • 它不能调用对象的构造函数或析构函数,因此不能与自定义类型的生命周期管理直接结合。

    内存管理和类型转换

    • new:new 和 delete 配对使用,内存管理更加直观和安全。new 可以根据类型自动计算内存大小,并且返回正确的类型指针。
    • malloc:malloc 和 free 配对使用,手动进行内存管理。必须使用 sizeof 来计算所需内存大小,并且必须进行强制类型转换。

    总结:newmalloc 的比较

    2.3 结构体和共用体的区别

    结构体:

    • 成员在内存中独立存储,每个成员占用独立的内存空间。

    • 内存占用是成员之和,每个成员都占用独立的空间。

    • 成员可以同时被访问,通过成员名字来访问。

    • 适合存储和处理多个不同类型的数据,如员工信息、图形对象等。

    • 对于结构体的不同成员赋值,对结构体的其他成员不受影响

    共用体:

    • 成员共享同一块内存空间,只能存储一个成员的值。

    • 内存占用是最大成员的大小,所有成员共享该空间。

    • 成员只能同时访问其中的一个,存取时要明确指定。

    • 适合存储和处理只使用其中一种类型的数据,可以节省内存空间或进行数据类型转换。

    • 对于联合体的不同成员赋值,将会对他的其他成员重写

    2.4 什么是野指针和悬挂指针?

    在 C++ 中,指针操作非常常见,但如果指针没有正确初始化或在内存释放后没有更新,就可能导致一些问题。常见的指针问题包括野指针悬挂指针

    野指针(Dangling Pointer)

    定义: 野指针是指向未知或不确定内存地址的指针。它可能指向未初始化的内存,或者指向已经释放的内存区域。

    产生原因:

    • 指针没有初始化,指向一个随机地址。
    • 指针在使用前没有明确赋值。

    解决方法:

    • 初始化指针,比如将指针设为 nullptr
    • 避免使用未初始化的指针

    • i 声明了一个未初始化的指针, 是一个野指针,它指向一个随机的、不确定的内存地址。

    剩余60%内容,订阅专栏后可继续查看/也可单篇购买

    作者简介:仅用几个月时间0基础天坑急转嵌入式开发,逆袭成功拿下华为、vivo、小米等15个offer,面试经验100+,收藏20+面经,分享求职历程与学习心得。 专栏内容:这是一份覆盖嵌入式求职过程中99%问题指南,详细讲解了嵌入式开发的学习路径、项目经验分享、简历优化技巧、面试心得及实习经验,从技术面,HR面,AI面,主管面,谈薪一站式服务,助你突破技术瓶颈、打破信息差,争取更多大厂offer。

    全部评论
    勘误2.9示例1:标题是无explicit的构造函数,但代码中有
    点赞 回复 分享
    发布于 03-22 15:52 重庆
    这就是顶级九八五的脑子吗,半年学这么多的同时还码字创作经营账号,太太太太太强了🤯
    点赞 回复 分享
    发布于 03-14 16:43 重庆
    3.10打卡
    点赞 回复 分享
    发布于 03-10 11:58 辽宁
    点赞 回复 分享
    发布于 02-25 15:48 浙江
    都是手打的咩
    点赞 回复 分享
    发布于 02-25 15:48 浙江
    结构体共用体对比实用
    点赞 回复 分享
    发布于 02-24 18:48 浙江
    C和C++区别讲得好
    点赞 回复 分享
    发布于 02-24 18:33 浙江
    好强
    点赞 回复 分享
    发布于 02-24 16:34 浙江

    相关推荐

    投递米哈游等公司6个岗位
    点赞 评论 收藏
    分享
    评论
    8
    8
    分享

    创作者周榜

    更多
    牛客网
    牛客企业服务