c++中的多线程写时复制
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586#include<iostream>#include<mutex>#include<memory>#include<shared_mutex>using namespace std;//写时复制包装器模板类template<typename T>class CowPtr{private: mutable shared_ptr<T> ptr; //mutable 关键字允许在 const 方法中修改这个成员变量 mutable shared_mutex mutex;//mutable 关键字允许在 const...
再探智能指针
又是许久未见的一期非人机博客,哈哈哈,感觉事好多(才不是寒假偷懒) 写完cc_muduo网络库之后,深感c++基础有待加深学习,于是重新看了一遍智能指针 众所周知,智能指针包括三种shared_ptr,weak_ptr,unique_ptr,我们一个个来 shared_ptr智能指针,作为c++独有的方式,相比malloc,free,以及new...
bind和回调函数的关系
在C++和其他编程语言中,**bind** 和 回调(Callback) 都是与函数调用有关的概念,但它们的作用和使用场景不同。接下来,我们来详细讲解它们的关系以及各自的功能。 回调(Callback)函数回调函数是一种设计模式,指的是将一个函数作为参数传递给另一个函数,并在某个事件发生时由后者调用这个函数。简单来说,回调函数是被“回调”执行的函数。 回调函数的作用 允许你在程序中实现灵活的控制流。 通过回调,你可以将具体的业务逻辑交给调用者来定义,而不是在框架或库中硬编码。 回调函数的典型示例123456789101112131415161718#include <iostream>using namespace std;// 回调函数类型void callback(int x) { cout << "Callback function called with value: " << x << endl;}// 使用回调的函数void processData(void...
thread_local的作用
thread_local修饰的变量,可以理解为每个线程独有的静态变量 thread_local 的作用thread_local 是 C++11 引入的一个关键字,它用于声明线程局部存储(TLS)。线程局部存储指的是每个线程都有自己的变量副本,而这些副本在不同线程之间互不干扰。每个线程访问 thread_local 变量时,都会得到该变量的独立副本。 作用thread_local 的主要作用是确保每个线程都有该变量的独立副本,避免不同线程之间对该变量的竞争和冲突。这在多线程程序中非常重要,特别是当不同线程需要独立的状态或数据时。 如何使用 thread_localthread_local 可以修饰普通的变量、静态变量、类成员变量等。 语法:1thread_local type variable_name; 例如: 1thread_local int counter = 0; // 每个线程都有自己的独立 counter 变量 示例1. 基本用法12345678910111213141516171819202122#include...
explicit关键字
explicit 关键字在 C++ 中,explicit 是一个用于构造函数的修饰符,其主要作用是 防止隐式类型转换,从而避免某些情况下的代码歧义或意外错误。 用法 修饰构造函数,防止隐式类型转换。 修饰带有单个参数的构造函数,避免单参数的构造函数被用作隐式类型转换运算符。 语法1234class ClassName {public: explicit ClassName(Type param);}; 为什么需要 explicit? 默认情况下,C++ 会允许单参数构造函数被隐式调用,用于进行类型转换。这种行为有时会导致意外的错误。 使用 explicit 可以禁止这样的隐式转换。 示例1. 没有使用 explicit123456789101112131415161718192021#include <iostream>class MyClass {public: // 单参数构造函数 MyClass(int value) : m_value(value) {} void...
懒加载
懒加载(Lazy Initialization 或 Lazy Loading)是一种设计模式或编程技巧,它的核心思想是:延迟初始化资源,只有在真正需要的时候才创建或加载这些资源。 懒加载的特点 避免不必要的开销 如果资源加载非常耗时或占用大量内存,懒加载可以减少程序启动时的资源占用。 提升性能 只有在资源被真正需要时才加载,减少了程序的启动时间。 按需加载 资源是否加载取决于程序运行时的实际需求,可能避免加载某些资源。 懒加载的使用场景 单例模式 在单例模式中,实例对象通常会在第一次访问时才创建。 例如,你的 Logger 类的实现:1234Logger &Logger::instance() { static Logger logger; // 静态变量只在第一次调用时初始化 return logger;} Logger 对象只有在调用 Logger::instance()...
仿函数
在 C++ 中,仿函数(Function Object 或 Functor) 是一种行为类似于函数的对象。仿函数是通过重载 operator() 运算符来实现的,这样一个对象就可以像函数一样调用。 仿函数的核心思想是:对象可以具有类似函数的行为,并且可以携带状态。这为设计灵活的函数调用方式提供了可能性,尤其是在 STL(标准模板库)中,仿函数被广泛应用于算法、容器操作等场景。 1. 仿函数的基本概念仿函数是通过在一个类中重载 operator() 运算符来实现的。这样,类的对象就可以被调用(表现得像一个函数)。 仿函数的基本语法12345678910111213141516#include <iostream>using namespace std;class MyFunctor {public: // 重载 operator() void operator()(int x) { cout << "Called with: " << x << endl; ...
可调用对象的绑定器和包装器
在 C++ 中,可调用对象的绑定器和包装器是用来简化或增强对函数(包括普通函数、成员函数、函数对象、Lambda 表达式等)的调用操作的工具。它们广泛用于泛型编程和 STL 算法中,以便将函数灵活地传递给算法或动态控制其行为。 1. 可调用对象的绑定器绑定器的作用是将一个可调用对象的一部分参数提前绑定,从而生成一个新的可调用对象。 C++11 起引入了 std::bind,用于创建一个可调用对象并绑定部分参数;在现代 C++(C++20)中,更推荐使用 Lambda 表达式 替代 std::bind。 1.1 std::bindstd::bind 是一个函数模板,它可以接受一个可调用对象(如普通函数、成员函数、函数对象等)及部分参数,并返回一个新的可调用对象,该对象可以像函数一样调用。 语法123#include <functional> // std::bind 所在的头文件std::bind(callable, arg1, arg2, ..., argN); callable:要绑定的可调用对象。 arg1, arg2, ...,...
模板
模板(Template)概述模板是 C++ 中的一种泛型编程机制,允许编写通用的代码,可以在不指定具体数据类型的情况下定义函数、类或结构体。模板的主要目的是提供代码的复用性和灵活性,从而支持处理多种数据类型的能力。 C++ 中的模板主要分为两种: 函数模板(Function Template) 类模板(Class Template) 1. 函数模板函数模板是定义一个可以操作多种数据类型的函数。通过模板,函数可以在调用时根据传递的参数类型自动生成具体的函数。 1.1 函数模板的基本语法12345678910template <typename T>T add(T a, T b) { return a + b;}int main() { cout << add<int>(3, 4) << endl; // 显式指定类型为 int cout << add(3.5, 4.2) << endl; // 隐式推导类型为 double return...
c++中的线程
在 C++ 中,线程是用来实现并发编程的重要工具,它允许程序同时执行多个任务。C++11 标准引入了多线程支持,主要通过 <thread> 标头文件提供相关功能,包括线程创建、管理和同步等。 1. 基本概念 线程是程序执行的基本单位,一个程序可以包含多个线程。 多线程可以提高程序效率,特别是在多核 CPU 上,每个线程可以在不同的核上运行。 C++ 提供的多线程功能包括: 线程的创建与管理(std::thread)。 同步机制(如互斥锁 std::mutex、条件变量 std::condition_variable 等)。 数据保护(如线程安全的操作)。 2. 创建和管理线程1) 创建线程线程可以通过 std::thread 创建,并且可以使用函数、lambda 表达式或可调用对象作为线程入口。 (a) 使用普通函数123456789101112#include <iostream>#include <thread>void threadFunction() { std::cout <<...