用于告诉编译器不要对标记为 volatile
的变量进行优化,以确保其值在程序执行期间不会被缓存或重新排序
volatile还可以告诉编译器不要将变量的值缓存在寄存器中,而是每次都从内存中读取。这对于与硬件通信或多线程编程等情况非常重要
volatile还可以提醒其他程序员或维护人员,这个变量是特殊的,可能会在不同的地方更改,因此要特别小心处理
&
符号声明,而指针使用*
符号。引用在声明时需要初始化,而指针可以稍后初始化或者指向不同的对象。*
来访问目标变量。const
关键字,可以声明一个常量,其值在初始化后不可更改,有助于提高代码的可读性和安全性。const
可用于声明成员函数,表示该函数不会修改类的成员变量。这有助于确保在调用函数时不会意外地修改对象的状态。const
表示该参数是只读的,不能在函数内部修改。这有助于传递参数时保护其内容。const
可以表示该函数返回一个常量值,不可用于赋值操作。总之,const
在C++中用于创建常量、指定不可修改的数据、保护函数参数和防止不必要的数据更改,有助于提高代码的可靠性和维护性。
const int *a; *//等于 int const \*a;*
int * const a;
int const * const a; *//等于 const int\* const a;*
以*为分界点,
当const在*的左边时,实际物体值不变
当const在*的右边时,指针不变
当const在*的两边时,指针和指向的数都不可变
即, 左物右指
这样来记比较方便!!
struct(结构体)
union(联合)
#define
const
const
创建的常量具有明确定义的数据类型,这提供了类型安全性。如果使用错误的类型,编译器将发出错误。而 #define
创建的常量只是文本替换,没有类型信息,可能导致类型错误。const
常量在编译后会保留类型信息,这对调试和代码可读性非常有帮助。#define
常量只是文本替换,不会在调试信息中显示。const
常量可以具有作用域,可以限定在特定的代码块中,而 #define
常量在整个文件中都有效。const
常量的地址,这对于处理常量数据很有帮助。使用 #define
常量时,它们没有确定的内存位置,无法使用指针。总之,虽然 #define
和 const
都可以用于定义常量,但 const
在类型安全性、调试可读性、作用域控制和指针关联方面提供了更多的优势。因此,现代C++编程中通常更倾向于使用 const
来定义常量。
new
和 delete
(C++中的运算符):
new
是C++中的运算符,用于在堆上动态分配内存,并返回分配内存的指针。它还会调用对象的构造函数。delete
是C++中的运算符,用于释放通过 new
分配的内存,并调用对象的析构函数。它与 new
配对使用,确保资源的正确释放。malloc
和 free
(C语言中的函数):
malloc
是C语言中的库函数,用于在堆上动态分配内存,返回一个指向分配内存的指针。它不会调用对象的构造函数。free
是C语言中的库函数,用于释放通过 malloc
分配的内存。它与 malloc
配对使用,确保资源的正确释放。关键区别:
new
和 delete
是C++特有的,与类和对象相关。它们处理内存和对象的生命周期。malloc
和 free
是C语言中的标准库函数,用于处理一般的内存分配和释放,不处理对象构造和析构。new
和 delete
以及 malloc
和 free
,但要小心避免混淆和内存泄漏。在现代C++中,推荐使用 new
和 delete
来进行内存管理,因为它们更安全,能够正确处理对象的构造和析构。
delete
用于释放单个对象的内存,而 delete[]
用于释放数组对象的内存。
如果使用 new
分配了单个对象的内存,应使用 delete
进行释放;如果使用 new[]
分配了数组对象的内存,应使用 delete[]
进行释放。
virtual
关键字进行声明,例如:virtual void myFunction() { /* 函数实现 */ }
。virtual
关键字和 = 0
进行声明,例如:virtual void myFunction() = 0;
。STL(Standard Template Library)是C++标准库中的一个重要组成部分,提供了各种通用数据结构和算法,以及用于处理这些数据结构的迭代器等工具。
容器(Containers):
算法(Algorithms):
sort
:对序列进行排序。find
:在序列中查找指定元素。for_each
:对序列中的每个元素执行指定操作。count
:计算序列中指定元素的数量。remove
:删除容器中的指定元素。迭代器(Iterators): 用于遍历容器中的元素,提供了统一的接口。
函数对象(Functors): 可以像函数一样使用的对象,用于自定义算法的行为。
适配器(Adapters): 提供了容器和迭代器之间的适配器,如栈适配器(stack adapter)和队列适配器(queue adapter)。
vector
是基于动态数组实现的。它在内存中分配一块连续的内存区域,当元素数量达到容量上限时,会重新分配更大的内存块,并将元素复制过去。list
是双向链表的实现。每个元素都包含一个指向前一个元素和后一个元素的指针。set
和 map
通常使用平衡二叉搜索树(如红黑树)来实现,以保持元素的有序性和快速查找。unordered_set
和 unordered_map
使用哈希表作为底层数据结构,以提供快速的查找和插入操作。为什么构造函数不定义
为什么析构函数定义
野指针不是NULL指针,是未初始化或者未清零的指针
delete
或free
释放动态分配的内存后,如果不将指针置为nullptr
(或NULL
),它可能仍然包含之前的内存地址,从而成为野指针。vector
使用动态数组(array)作为底层数据结构,因此元素在内存中是连续存储的。这使得对元素的随机访问非常高效,但在插入和删除元素时可能涉及数据的移动。vector
的元素是连续存储的,它通常会占用更少的内存,因为不需要额外的指针。list
使用双向链表作为底层数据结构,每个元素都包含了指向前一个和后一个元素的指针。这使得插入和删除元素非常高效,但随机访问需要遍历链表,效率相对较低。list
的元素需要额外的指针来维护链表结构,因此通常占用更多内存。这些机制提供了更灵活的访问控制,但需要谨慎使用,以避免破坏类的封装性和安全性。
在C++中,struct
和class
都是用于定义用户自定义数据类型的关键字,它们有一些区别,主要涉及到成员的默认访问权限
struct
:成员的默认访问权限是public
,即结构体中的成员可以被外部访问。class
:成员的默认访问权限是private
,即类中的成员默认是私有的,无法被外部直接访问。struct
:通常用于表示一组相关的数据,类似于记录,其成员通常是公有的,用于数据聚合。class
:通常用于表示一个抽象的数据类型,其成员可以包含数据和成员函数,用于封装数据和行为。struct
:支持继承,可以派生自其他结构体或类。class
:同样支持继承,可以派生自其他类。对于双引号包含的头文件,查找头文件默认为当前头文件目录下查找。
而尖括号查找头文件默认是编译器设置的头文件路径下查找
智能指针是C++中的类模板,用于管理动态分配的内存资源。它们自动处理内存的分配和释放,从而减少内存泄漏的风险。
C++11引入了std::shared_ptr
和std::unique_ptr
std::shared_ptr
允许多个智能指针共享同一个对象,维护一个引用计数。当引用计数为零时,对象将被销毁。std::unique_ptr
代表独占所有权,只有一个智能指针可以拥有对象。它更轻量,因为不需要维护引用计数。智能指针通常比原始指针稍微慢一些,因为它们需要额外的开销来管理引用计数等信息。但在现代C++中,这种性能差异通常可以忽略不计。
for
循环: 简化了遍历容器和数组的操作。std::shared_ptr
和 std::unique_ptr
等用于更安全地管理动态内存。std::vector
,已经实现了移动语义,使得容器的操作更加高效。TCP:
UDP:
TCP适用于需要可靠传输的应用,而UDP适用于实时性要求高、可以容忍数据丢失的应用。
三次握手是TCP协议中用于建立连接的过程
四次挥手是TCP协议中用于关闭连接的过程
extern "C"
是C++中用于与C语言代码进行交互的关键字,它告诉C++编译器按照C语言的规则处理函数名,以确保正确的链接和符号匹配。这通常用于混合编程,以确保C++代码能够与C代码协同工作。
HTTP和HTTPS都是用于在网络上传输数据的协议
std::mutex
是C++标准库中的互斥锁,最常见的锁之一。它用于实现基本的线程互斥,确保同时只有一个线程可以访问临界区。你可以使用 std::mutex
来保护共享资源,以确保线程安全。1. 二叉树(Binary Tree):
2. 二叉搜索树(Binary Search Tree,BST):
3. 平衡二叉树:
4. B树和B+树:
总的来说,AVL树提供了更严格的平衡性,但因此可能在某些操作上更慢。红黑树在平衡和性能之间取得了一种平衡,适用于广泛的应用场景。它们都是平衡二叉树。
数组指针是一个指向数组的指针。它指向整个数组,而不是数组中的单个元素。
指针数组是一个数组,其中的元素都是指针。
new
和 delete
运算符或将它们设置为私有来禁用堆上的动态内存分配。此外,在函数中声明和使用该类的对象,以限制其生命周期仅在函数范围内,从而强制将其分配到栈上。这样可以确保对象不会在堆上创建。inline
关键字定义#define
指令定义。总之,内联函数提供了更安全、更可读且更易维护的代码重用方式,而宏定义提供了更灵活但更容易出错的文本替换机制。在C++中,应尽量使用内联函数以提高代码的可维护性和安全性。
RabbitMQ是一种消息队列中间件,它用于在分布式系统中实现异步通信和解耦组件之间的通信。