C++ 面向对象_7
总结 C++ 中的 “三五法则”:析构、拷贝与移动语义
在 C++ 中,资源管理是一个核心问题,特别是当类中包含动态分配的资源(如堆内存)时,“三五法则” 提供了一个设计类时应该遵循的指导原则,以确保资源被正确管理。
这包括如下:
资源正确释放:当对象生命周期结束时,其管理的资源必须被释放(例如 delete 内存)。这通常由析构函数完成。
资源正确复制:当对象被复制时(通过拷贝构造或拷贝赋值),其管理的资源需要被正确处理。
资源正确移动:当对象被移动时(通过移动构造或移动赋值),其管理的资源需...
SG90舵机驱动
SG90 伺服电机驱动
舵机是通俗的叫法,它的本质是一个伺服电机,也可以叫做位置(角度)伺服驱动器。一般被应用在那些需要控制角度变化的系统中,可以方便的实现转动任意的角度,实现控制角度的变化。
工作原理
sg90 舵机模块内有控制电路,控制信号通过信号线输入到内部的控制电路中,调制芯片将输入的信号进行调制,获得直流偏置电压。然后再由内部的基准电路产生周期为 20ms,宽度为 1.5ms 的基准信号,将直流偏置电压和电位器电压进行比较,从而获得输出的电压差。由电压差控制舵机的转动,这个电压差的正负控制舵机正...
C++ 面向对象_6
拷贝赋值与移动赋值函数
拷贝赋值函数(Copy Assignment Operator):类的特殊成员函数,用于将一个已有对象的内容复制到另一个已有对象中。它通常以 operator= 的形式重载,返回类型为当前类的引用(ClassName&),参数为常量引用(const ClassName&)。
ClassName& operator=(const ClassName& other);
拷贝赋值涉及深拷贝和浅拷贝(取决于实现方式),会复制源对象的状态到目标对象中,通常需要考虑资源管理(如动态内存分配...
C++ 面向对象_5
C++ 析构函数
析构函数是 C++ 中的一个特殊成员函数,它在对象生命周期结束时自动被调用。与构造函数负责初始化对象不同,析构函数负责在对象被销毁前进行必要的清理操作。
析构函数的名称由 ~ 开头,后面跟着类名,它不接受任何参数,也不返回任何值。每个类只能有一个析构函数。
析构函数主要做什么?
析构函数在 C++ 的内存管理和资源控制中起着关键的作用,比如,释放对象动态分配的内存:当一个对象在堆上分配了内存(使用 new 关键字),这些内存需要在对象被销毁时释放,否则会造成内存泄漏。除了动态分配的内存,析...
C++ 面向对象_4
C++ 构造函数
构造函数是一种特殊的成员函数,当创建类的对象时自动被调用。它的主要任务是初始化对象的数据成员,确保对象在创建时处于有效状态。构造函数与类同名,且没有返回类型(甚至不包含void),构造函数支持重载以接受不同的参数。
可以简单写一个构造函数,示例如下:
class Person {
private:
std::string name;
int age;
public:
// 带参数的构造函数
Person(const std::string& n, int ...
C++ 面向对象_3
C++ 访问限定符与友元
访问限定符
访问限定符(Access Specifiers)是 C++ 中用于控制类成员(包括成员变量和成员函数)访问权限的关键字。它们定义了类内部成员对外部代码的可见性和可访问性,主要用于实现封装(Encapsulation),这是面向对象编程的核心原则之一。C++ 中有三种主要的访问限定符:
public:公共访问权限,类内的成员可以被类外部的任何代码访问。
private:私有访问权限,只有类内部的成员函数或友元(friend)可以访问,外部代码无法直接访问。
protec...
C++ 面向对象_2
C++ 成员函数
在 C++ 中,成员函数(Member Function)是定义在类(class)或结构(struct)内部的函数,它属于该类的成员。成员函数可以直接访问类的所有成员,包括私有(private)、保护(protected)和公有(public)的成员变量和函数。成员函数通常用来操作类的对象数据或提供类的行为接口。
简单来说,成员函数是类的一部分,与类的对象绑定在一起,描述了对象能够执行的操作。例如,在一个表示“汽车”的类中,成员函数可能是“启动引擎”或“加速”。
为什么需要成员函数?
基于...
C++ 面向对象_1
C++ 静态数据
在 C++ 中,静态数据(Static Data)是指使用 static 关键字修饰的数据,其生命周期与程序的整个运行时相同,而不是局限于某个作用域。静态数据在程序启动时分配内存,在程序结束时释放。与普通的局部变量或动态分配的变量不同,静态数据的生存期是全局的,但其作用域可以是局部的或全局的。
静态数据可以出现的场景:
全局/命名空间作用域中的静态变量:在文件级别定义的静态变量,只在定义它的文件中可见。
函数中的静态局部变量:在函数内部定义,只初始化一次,且在函数调用之时保持其作用域。
...
C++ 面向对象_0
C++ 结构体--向面向对象的过渡
C++ 中的结构体是从 C 语言继承而来,允许程序员将相关的数据组合在一起形成一个抽象数据类型,同时拓展了面向对象的设计思想
声明(declaration)和定义(definition)
声明是向编译器引入一个标识符(如变量、函数、类、结构体等)的名称和类型,但不分配存储空间或提供完整实现。声明的主要目的是告诉编译器"这个东西存在",以便编译器在遇到该标识符的使用时能够知道它的类型和基本特性。在声明时,对于变量来讲并不提供分配内存的操作,对于函数来讲并不提供具体的实现,只...
总结 C++ 泛型算法_0
泛型算法
泛型算法是 C++ 标准库中的一个强大特性,它为程序员提供了处理各种数据类型的通用工具。
什么是泛型算法?
泛型算法可以理解为泛化各种类型的通用操作逻辑,是一组独立于特定数据类型和数据结构的算法,是操作各种数据类型的通用实现逻辑,可以操作不同类型的数据容器。这些算法被设计为可以处理各种数据类型,而不需要为每种类型编写专门的代码。C++ 标准模板库(STL)中的泛型算法主要在 <algorithm>、<numeric>和 <functional>头文件中定义。
泛型算法的核心特定是通过模板技术实现对...
总结 C++ 容器
关联容器
Set
set 是 C++ 标准模板库(STL)中的一种关联容器,定义在 <set> 头文件中。它是一个有序的集合,用于存储唯一元素,即不允许重复值。set 的底层实现通常基于红黑树(一种自平衡二叉搜索树),这使得它能够高效地支持插入、删除和查找操作,同时保持元素的有序性(默认按升序排列)。
set 的 key 是模板 T 对应的类型对象,value 是 set 中是否存在这个类型的对象,即 true 或者 false。
set 具有唯一性,每个对象在 set 中只出现一次,重复出现的对象会被自...
总结 C++ 动态内存管理_1
unique_ptr
unique_ptr 是 C++11 引入的一种智能指针(一种抽象数据类型),定义在 <memory> 头文件中。它是标准库提供的一种工具,用于管理动态分配的内存,确保该类型的对象维护的指针拥有内存的独占所有权(unique ownership)。换句话说,一个 unique_ptr 类型的对象维护的指针在整个程序的生命周期内只有一个,这不同于 shared_ptr 对象维护的指针可以是同一个,即被共享。当 unique_ptr 对象被销毁(例如离开作用域)时,它所管理的动态内存会自动...
错误
wifi一直连接不上咋回事
总结 C++ 动态内存管理_0
C++ 动态内存管理总结
为什么强烈不建议重载系统自身的 operator new 和 operator delete 行为
在 C++ 中,new 和 delete 是内存分配和释放的核心操作,默认由标准库提供行为实现。这些行为经过了高度优化,能够很好地与操作系统、编译器以及运行时环境协同工作,高度耦合。虽然允许开发者通过重载全局的 operator new 和 operator delete 来自定义内存管理行为,但这会带来很多问题。比如,破坏标准库的组件,性能问题,调试和维护难度,与第三方库的兼容性问...
总结 C++ 数组遍历
总结 C++ 数组遍历
C++ 中求数组元素个数的方式
1. 使用 sizeof 运算符
sizeof(array) / sizeof(array[0])
sizeof(array) 返回数组总的字节数。
sizeof(array[0]) 返回数组单个元素的字节数。
将总字节数除以单个元素的字节数,即可得到数组的元素个数。
int arr[5];
std::cout << sizeof(arr) / sizeof(arr[0]); // 输出 5
优点:简单、直接,适用于固定大小的数组。
缺...
理解 C++ 自动类型推导·:decltype
decltype
博主前面引入了 auto 的自动类型推导,decltype() 是 C++11 引入的另一个类型推导工具,用于获取表达式或变量的类型。它可以在编译期静态地分析表达式的类型并返回对应的类型定义,而不会实际执行表达式。
简单来说,decltype() 的作用是:评估一个表达式的类型并返回该类型。
2. 为什么需要 decltype()?
有时候类型过于复杂,例如标准库容器中的迭代器类型;decltype() 可以使代码更简洁。
在模板代码中,需要确定某些表达式的返回类型或变量的类型。
结合...
理解 C++ 自动类型推导:auto
C++ 中的自动类型推导:auto 全面总结
auto 是 C++11 引入的关键字,用于自动类型推导。它让编译器根据变量的初始化表达式来决定变量的类型,而不需要程序员显式指定类型。
为什么需要 auto?
引入 auto 关键字有几个重要原因:
简化复杂类型声明:在现代 C++ 中,类型名称可能非常冗长,特别是使用模板时。例如:
std::map<std::string, std::vector<int>>::iterator it = myMap.begin();
使用 auto 后:
auto ...
理解 C++ 常量和常量表达式
理解 C/C++ 常量与常量表达式
博主之前有篇文章讨论了 C/C++ 程序在被 gnu 链接器 ld 链接后的内存布局,内存通常被分为几个主要区域:
代码段(Text/Code Segment):存储程序的可执行指令。
数据段(Data Segment):
初始化数据段:存储已初始化的全局变量和静态变量。
未初始化数据段(BSS):存储未初始化的全局变量和静态变量。
堆(Heap):用于动态内存分配。
栈(Stack):用于存储栈帧。
以下面这段代码为例,在 main 函数内部定义一个局部常量:...
C/C++ 内存布局
C/C++ 程序的内存布局 (Memory Layout In C/C++)
上图展示了程序中内存布局(Memory Layout)的关键构成(Key Components),其中黄色部分称为动态内存区(Dynamic memory area),其中包括堆内存(Heap)和栈内存(Stake),下面三个不同颜色的部分我们各称为一个段(Segment),整个程序有自己的虚拟内存地址空间,由操作系统映射到实际的物理内存地址,从程序自身的角度看它认为自己在运行时是占用连续的一整块内存空间,至于物理内存如何存储运...
理解 C++ 引用的实现
理解 C++ 的引用实现
在 C++ 中,引用(reference)是一种特殊的机制,它允许你为一个已有的变量创建一个 “别名(alias)”。通过引用,你可以直接操作原始变量,而不是创建一个新的副本。引用本质上是一个变量的 “第二个名字”,它与原始变量绑定在一起,任何对引用的操作都会直接影响原始变量。
引用通过在变量声明时使用 & 符号来定义。定义引用时,必须立即初始化,并且它必须绑定到一个已存在的变量上。引用本身不是一个独立的实体,而是直接指向它所引用的变量。
语法示例:
int a = 10; ...