068-单例模式
单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。 懒汉模式(Meyers’ Singleton)123456789101112class Singleton{public: static Singleton& getInstance(){ static Singleton obj; // 静态局部变量 return obj; } Singleton(const Singleton&) = delete; // 显示拒绝拷贝构造和复制构造 Singleton& operator=(const Singleton&) = delete;private: Singleton() = default; ~Singleton() = default;}; 通用化1234567891011121314template<typename T>class Singleton{public: static...
067-read/write和recv/send的区别
read()/write() 和 recv()/send() 是用于数据传输的系统调用,但它们有一些区别: 通用性: read() 和 write() 是通用的 I/O 操作函数,可以用于文件、管道、套接字等各种文件描述符。 recv() 和 send() 专门用于套接字操作,提供了一些额外的功能。 功能性: recv() 和 send() 可以指定额外的标志(flags),如 MSG_DONTWAIT、MSG_PEEK 等,这些标志可以改变函数的行为。 read() 和 write() 没有这些额外的标志。 参数: recv() 和 send() 的参数中包含一个 flags 参数,用于指定操作的行为。 read() 和 write() 没有 flags 参数。 使用场景: 在网络编程中,通常使用 recv() 和 send(),因为它们提供了更灵活的控制。 对于文件 I/O,通常使用 read() 和 write()。 总结来说,recv() 和 send() 是为网络编程设计的,提供了更多的控制选项,而...
066-生产者消费者模型
要实现 SCPI 回复与请求的匹配,可以考虑使用生产者-消费者模式或线程间同步机制。以下是一个简化的实现思路: 使用队列:可以使用一个线程安全的队列来存储请求和对应的回复。 生产者线程:负责发送 SCPI 命令并将请求信息(如请求 ID)放入队列。 消费者线程:负责从队列中取出请求信息,等待并接收对应的回复。 以下是一个简化的代码示例,展示如何使用 C++的线程和队列来实现这一模式: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152#include <iostream>#include <thread>#include <queue>#include <mutex>#include <condition_variable>#include <string>#include <utility>std::queue<std::pair<int,...
065-cpp-sleep
C++ 休眠函数让我用中文解释这两种休眠方式的区别: std::this_thread::sleep_for 1std::this_thread::sleep_for(std::chrono::milliseconds(100)); // C++11 方式 这是 C++11 引入的现代休眠方法 跨平台兼容性好 可以使用不同的时间单位(毫秒、微秒、秒等) 提供类型安全 可以与其他 C++时间相关的功能无缝配合 精度依赖于操作系统实现 usleep 1usleep(100000); // 参数单位是微秒 POSIX 系统的传统 C 函数 只在 UNIX/Linux 系统上可用 只接受微秒作为参数单位 参数类型是无符号整数 在某些系统上已经被废弃 可能会被信号中断 建议: 在现代 C++代码中,推荐使用std::this_thread::sleep_for 如果是只针对 UNIX/Linux 的老代码,usleep也是可以接受的 如果需要高精度定时,两者都不够理想,应该考虑使用专门的实时编程方案 示例对比: 12345//...
064-数据结构
常见概念随机访问随机访问(Random Access)是指在数据结构中,可以在常数时间内(O(1))直接访问任意一个元素,而不需要从头开始遍历数据结构。数组(Array)是支持随机访问的典型数据结构,因为可以通过索引(数据地址+偏移量)直接访问任意位置的元素。 在支持随机访问的数据结构中,元素的存储位置是连续的,这使得通过计算偏移量来直接定位元素成为可能。相比之下,链表(Linked List)不支持随机访问,因为访问某个元素需要从头开始逐个遍历,时间复杂度为 O(n)。 随机访问的优势在于其高效性,特别是在需要频繁访问或修改特定位置的元素时。然而,这种高效性通常是以牺牲插入和删除操作的效率为代价的,因为在数组中插入或删除元素可能需要移动大量数据。 哈希表哈希表就是键值对吗哈希表(Hash Table)确实是基于键值对(key-value...
063-模板
模板参数会保留其传入类型的所有修饰符在 C++中,模板参数会保留其传入类型的所有修饰符,包括const和引用(&或&&)。这意味着如果你传递一个const类型或引用类型作为模板参数,模板会保留这些修饰符。 例如: 123456789101112131415161718template <typename T>void func(T param) { // param的类型会保留T的所有修饰符}int main() { const int a = 10; func(a); // T为const int int b = 20; func(b); // T为int int& c = b; func(c); // T为int& const int& d = a; func(d); // T为const...
062-const
基本数据类型和字面值, 直接传值, 不要使用const&在 C++中,const&通常用于避免拷贝传递参数,尤其是对于较大的对象。然而,对于基本数据类型(如int、float等),传递它们的引用(包括const&)通常没有太大意义,因为它们本身就很小,拷贝的开销很低。对于基本数据类型,这种做法是可以的,但并不是必要的。你可以直接传值而不是引用,尤其是当你传递的是字面值(如0和1)时。 即: 基本数据类型和字面值, 直接传值, 不要使用const& 函数参数使用const在 C++中,使用const来修饰函数参数可以防止在函数内部修改这些参数的值。对于基本数据类型(如int、float等),使用const来修饰传值参数通常没有太大意义,因为传值本身就意味着在函数内部的修改不会影响到外部。 然而,如果你希望明确表达参数在函数内部不应被修改的意图,或者为了代码的一致性,你可以使用const来修饰传值参数。这样做不会影响性能或功能,但可以提高代码的可读性。
061-右值引用
右值引用右值引用只能绑定到临时对象 所引用的对象将要被销毁 该对象没有其他用户 意味着, 使用右值引用的代码可以自由地接管所引用的对象的资源 变量是左值, 离开作用域才会销毁, 所以不能将一个右值引用直接绑定到一个变量, 即使这个变量是右值引用类型 移动语义可以销毁一个 std::move 后的源对象, 也可以赋予新值, 但不能使用一个 std::move 后的对象的值 std::move 是一个标准库函数模板。它的目的是显式地将一个左值转换为右值引用,以便可以将其转移到另一个对象中,而不是进行复制。以下是逐步解析代码的细节: 代码解释123456template <typename T>typename remove_reference<T>::type &&move(T &¶m) { using ReturnType = typename remove_reference<T>::type &&; return...
060-cpp成员函数
在 C++中,类的成员函数通常包括以下几种类型: 构造函数(Constructor): 用于初始化对象。构造函数的名称与类名相同,没有返回类型。 可以有多个构造函数(重载),以支持不同的初始化方式。 析构函数(Destructor): 用于清理对象。析构函数的名称是类名的前面加上波浪号(~),没有返回类型,也没有参数。 在对象生命周期结束时自动调用。 拷贝构造函数(Copy Constructor): 用于复制对象。通常用于对象的复制初始化。 形如:ClassName(const ClassName &other) 赋值运算符重载(Assignment Operator Overload): 用于对象的赋值操作。 形如:ClassName& operator=(const ClassName &other) 移动构造函数(Move Constructor): 用于移动语义,提高性能。 形如:ClassName(ClassName &&other) 移动赋值运算符重载(Move Assignment...
059-int赋值给char
int 直接赋值给 char 会怎么样在 C++中,将一个 int 类型的值直接赋值给一个 char 类型的变量时,可能会发生以下情况: 截断:char 类型通常是 1 字节(8 位),而 int 类型通常是 4 字节(32 位)或更多。因此,当 int 的值超出 char 的表示范围时,只有最低的 8 位会被保留,其余的位会被截断。这可能导致数据丢失或值的改变。 符号扩展:如果 char 是有符号的(signed char),并且 int 的值超出了 char 的正数范围(通常是 -128 到 127),则可能会导致符号扩展问题,导致负值。 未定义行为:如果 int 的值超出了 char 的表示范围,可能会导致未定义行为,具体表现取决于编译器和平台。 例如: 12int largeValue = 300;char smallValue = largeValue; // smallValue 可能会变成 44,因为 300 的最低 8 位是 44 为了避免这些问题,通常建议在赋值前进行显式的类型转换,并确保值在目标类型的范围内: 12int largeValue =...