C++
文章平均质量分 72
个人笔记,总结
物随心转
子曰:“学而时习之,不亦说乎?”
展开
-
std::move失效问题
在C++中,std::move是一个用于将对象转移所有权的函数模板,它将对象的状态从一个对象转移到另一个对象,通常用于优化移动语义。从代码可以看出,std::move本质上是调用了static_cast做了一层强制转换,强制转换的目标类型是。那么,为什么我们通常使用std::move实现移动语义,可以将一个对象的数据移给另外一个对象?结合本文最初的问题,在lambda中move没有生效,显然也是std::move强转的类型不是。然后触发了移动构造函数,在移动构造函数中,完成了对象b的数据到对象a的移动。转载 2023-09-06 22:00:05 · 554 阅读 · 0 评论 -
shared_ptr产生内存泄漏的场景
使用 shared_ptr 可以帮助管理动态分配的内存,它使用引用计数的方式来跟踪共享对象的引用数量,当引用计数为零时,会自动释放内存。原创 2023-07-07 10:52:41 · 1649 阅读 · 0 评论 -
C++的std::apply
一、介绍std::apply是 C++17 中引入的一个函数模板,位于头文件中。它允许以元组的方式将参数传递给一个可调用对象(函数、函数指针、成员函数指针、函数对象等)。std::apply其中,F是可调用对象的类型,Tuple是一个std::tuple或类似的可转换为元组类型的对象。std::apply将元组t中的元素作为参数传递给可调用对象f并执行它。它返回可调用对象的结果。原创 2023-07-03 22:00:05 · 1173 阅读 · 0 评论 -
智能指针的deleter机制
智能指针的deleter机制是指,当智能指针的引用计数降为0时,智能指针会自动调用一个指定的析构函数(deleter)来释放所管理的内存。这个析构函数通常是一个函数对象,可以是一个函数指针、一个lambda表达式或者一个重载了函数调用运算符的类对象。智能指针的deleter机制可以确保在任何情况下都能正确地释放内存,包括在异常情况下和多线程环境下。原创 2023-07-03 21:41:53 · 666 阅读 · 0 评论 -
C++ 单例模式总结
单例模式是一种常见的设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。这个模式通常用于需要限制系统中某个类的实例数量的情况,例如数据库连接池、线程池、缓存等。使用单例模式可以避免在系统中创建多个实例,从而节省系统资源和提高性能。在单例模式中,通常会将类的构造函数设为私有,这样外部就无法通过直接实例化该类来创建新的实例。而是通过一个静态方法或属性来获取该类的唯一实例。如果该类的实例不存在,则该方法或属性会创建一个新的实例并返回,否则直接返回已有的实例。原创 2023-06-27 21:57:23 · 1040 阅读 · 0 评论 -
C++的 std::construct() 与std::destroy()
和是C++ STL中的函数模板,用于在已分配的存储区域中构造或销毁对象。这些函数通常用来和C++ STL容器结合使用,例如std::list等std::construct 可以在预分配的内存空间上使用所提供的参数列表构造对象,而不需要分配新的内存空间。其中,T 可以是任意类型,Args 为对象初始化所需的参数列表。p 是一个指针,指向构造的对象的存储位置。传递给 construct 的指针 p 必须指向已经预分配的内存空间,否则行为是未定义的;原创 2023-06-14 21:55:13 · 1993 阅读 · 0 评论 -
C++条件变量condition_variable
针对类似的场景,我们推荐您用条件变量来实现,头文件。和互斥锁、信号量类似,条件变量本质也是一个全局变量,用于多线程之间关于共享数据状态变化的通信。当一个动作需要另外一个动作完成时才能进行,即:当一个线程的行为依赖于另外一个线程对共享数据状态的改变时,这时候就可以使用条件变量。一个条件变量可以阻塞多个线程,这些线程会组成一个等待队列。当条件成立时,条件变量可以解除线程的“被阻塞状态”。原创 2023-05-24 21:55:30 · 2522 阅读 · 0 评论 -
C++移动构造函数
移动构造函数是参数类型为右值引用的拷贝构造函数类名 ( 类名&&(1)(C++11 起)class_name ( 类名&&(2)(C++11 起)class_name ( 类名&&) = delete;默认情况下,左值初始化同类对象只能通过拷贝构造函数完成,如果想调用移动构造函数,则必须使用右值进行初始化。C++11 标准中为了满足用户使用左值初始化同类对象时,也通过移动构造函数完成的需求,新引入了 std::move() 函数,它可以将左值强制转换成对应的右值,由此便可以使用移动构造函数。原创 2023-05-14 11:46:07 · 1652 阅读 · 3 评论 -
C++的对象池实践
对象池原创 2023-02-17 21:06:03 · 871 阅读 · 1 评论 -
__attribute__((weak))的使用
C++原创 2023-02-15 21:57:00 · 426 阅读 · 0 评论 -
在指定内存上创建对象——placement new机制
申请内存转载 2022-12-25 20:36:20 · 490 阅读 · 0 评论 -
C++内存池
内存池转载 2022-12-14 21:48:40 · 2803 阅读 · 0 评论 -
C++的map的自定义排序
map排序转载 2022-11-30 22:02:20 · 4450 阅读 · 0 评论 -
Priority_queue的less是升序还是降序
优先队列原创 2022-11-14 22:52:56 · 592 阅读 · 0 评论 -
C++ map的底层实现为什么是红黑树
map的底层原理转载 2022-11-12 17:55:53 · 1316 阅读 · 0 评论 -
C++的mutable
mutual转载 2022-10-26 22:14:11 · 553 阅读 · 0 评论 -
C++实现一个线程池
多线程原创 2022-09-17 22:37:34 · 3963 阅读 · 1 评论 -
C++多线程join,detach
一、介绍主线程从main()函数开始执行,我们创建的线程也需要一个函数作为入口开始执行,所以第一步先初始化函数。整个进程是否执行完毕的标志是主线程是否执行完毕,一般情况下,如果想要保持子线程的运行状态,那么要主线程保持运行二、使用join(),阻塞主线程,等待子线程执行完毕后,才到主线程执行。detach(),分离主线程,主线程和子线程各走各的,所以会出现多次运行会发现,运行结果可能不同,这时候需要考虑一个问题,主线程如果执行完了,子线程还没跑完,这就可能出现一定问题了。joinabl.原创 2021-09-12 22:24:30 · 1949 阅读 · 0 评论 -
C++之std::promise
一、介绍std::promise是C++11并发编程中常用的一个类,常配合std::future使用。std::promise提供了存储值的功能,这些值后来会通过std::promise对象创建的std::future对象异步获得。注意:std::promise对象只能使用一次。二、实例在主函数(主线程)中声明 promise 及其对应的 future,在某个线程中传入 promise 并进行运算;在另一个线程中出入 future, 可利用get得到前一个线程中计算的结果;#incl原创 2022-05-23 23:34:07 · 2232 阅读 · 0 评论 -
C++的std::packaged_task
一、介绍C++11中的std::packaged_task是个模板类。std::packaged_task包装了任何可调用目标(函数、lambda表达式、bind表达式、函数对象),以便可以被异步调用。它的返回值或抛出的异常存储在一个共享状态中,该共享状态可以通过std::future对象访问。函数原型template< class R, class ...ArgTypes >class packaged_task<R(ArgTypes...)>;二、实例#原创 2022-05-27 22:53:54 · 543 阅读 · 0 评论 -
C++中有些重载运算符为什么要返回引用
C++原创 2022-08-29 22:21:07 · 1302 阅读 · 0 评论 -
C++解析json
解析json原创 2022-08-06 09:45:05 · 1549 阅读 · 4 评论 -
C++11 的 运行时类型识别type_info
一、type_info与typeid类type_info保存关于类型的特定于实现的信息,包括类型的名称,以及比较两个类型是否相等或排序顺序的方法。 这是typeid操作符返回的类。具有如下特点:(1)这个类的构造函数是private的,因此用户不能直接构造这样的对象,只能通过typeid()函数来获取这个对象. (2)这个类对外提供了name(),operator==()等方法供用户使用. (3)typeid()可以对基本的数据类型和对象进行操作,这种情况下,是在编译期静...原创 2022-05-30 22:41:33 · 986 阅读 · 0 评论 -
C++的二分查找函数
lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。一、lower_bound( )lower_bound 的作用是在已经排好序的数组中返回第一个大于等于(不小于)你所给定的值。源码版本一template<class ForwardIt, class T>ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value){ F原创 2022-05-27 22:54:56 · 6113 阅读 · 1 评论 -
C++的std::enable_if
一、介绍enable_if的主要作用就是当某个condition成立时,enable_if可以提供某种类型。源码// STRUCT TEMPLATE enable_iftemplate <bool _Test, class _Ty = void> //泛化版本struct enable_if {}; // no member "type" when !_Test template <class _Ty> //偏特化版本:怎么理解:只有这个偏特化版本存在...原创 2022-05-06 22:40:32 · 2746 阅读 · 3 评论 -
C++的std::is_same与std::decay
一、背景有一个模板函数,函数在处理int型和double型时需要进行特殊的处理,那么怎么在编译期知道传入的参数的数据类型是int型还是double型呢?#include <iostream>template<typename T>void typeCheck(T data){ // check data type //std::cout<< out put the type}二、std::is_same<type_trai原创 2022-05-05 22:34:23 · 2729 阅读 · 0 评论 -
C++的substr实现分割字符串
一、介绍原型:string substr ( size_t pos = 0, size_t n = npos ) const;形式 : str.substr(pos, len)返回值: string,包含str中从pos开始的len个字符的拷贝(pos的默认值是0,len的默认值是s.size() - pos,即不加参数会默认拷贝整个str)异常 :若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则subst原创 2022-04-19 22:36:57 · 2307 阅读 · 1 评论 -
C++类中const修饰的函数与重载
一、重载的定义重载声明是指在同一个作用域内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。不能仅通过返回类型的不同来重载函数。二、值传递作为参数,加const不构成重载int test(const int a){ return a;}int test(int a){ return a;}int main(){ int value = 1; std::cout << test(val原创 2022-04-18 22:39:10 · 3158 阅读 · 0 评论 -
C++11的消息总线
一、什么是消息总线在大规模的软件开发过程中,对象很多,关联关系非常复杂,如果没有统一的、简洁的方法去管理这些对象关系,会导致对象关系复杂,后期维护困难。基于消息总线技术可以解决这些问题。对象之间只通过消息联系,不是通过直接的依赖或者关联。在消息总线中,对象是通过消息来联系,消息即是对象的关系,只需要在消息总线中管理这些消息,不用关心具体哪些对象之间有关联,便于统一管理。二、消息总线包含的内容通用的消息定义定义一种通用的消息格式,让所有的对象都能接受。通用的消息类型完整的定义是主题+泛原创 2022-03-22 23:19:50 · 3041 阅读 · 0 评论 -
C++ std::shared_mutex读写锁
一、介绍C++17中引入std::shared_mutexstd::shared_mutex用于管理可转移和共享所有权的互斥对象,适用场景比较特殊:一个或多个读线程同时读取共享资源,且只有一个写线程来修改这个资源,这种情况下才能从shared_mutex获取性能优势互斥量管理类-锁shared_lock是read lock。搭配std::shared_mutex使用,被锁后仍允许其他线程执行同样被shared_lock的代码。 lock_guard和unique_lock是write loc转载 2022-03-13 22:42:50 · 7769 阅读 · 6 评论 -
C++的tuple
一、介绍tuple是一个固定大小的不同类型值的集合,是泛化的std::pair。我们也可以把它当做一个通用的结构体来用,不需要创建结构体又获取结构体的特征,在某些情况下可以取代结构体使程序更简洁,直观。std::tuple理论上可以有无数个任意类型的成员变量,而std::pair只能是2个成员,因此在需要保存3个及以上的数据时就需要使用tuple元组了。二、tuple的使用 std::string name; std::tuple<string &, int>.原创 2022-03-06 19:53:39 · 7347 阅读 · 0 评论 -
C++显示链接与隐式链接
Explicit Linking 即显式链接,Implicit Linking 即隐式链接,这两种都是动态链接库的使用方式。一、显式链接动态链接库通常都有其导出函数列表, 告知其他可执行程序可以使用它的哪些函数。可执行程序使用这些导出函数有两种方式:一是在运行时使用主动加载动态库的函数,Linux 里比如用 dlopen 函数打开并加载动态库,Windows 里一般用 LoadLibrary 打开并加载动态库,只有当程序代码执行到这些函数时,其参数里的动态库才会被加载,这就是显式链接。显式链接方式是转载 2022-02-19 13:35:46 · 1428 阅读 · 0 评论 -
C++之关联容器的erase使用
对于关联容器(如map,set,multimap,multiset),删除当前的iterator,仅仅会使当前的iterator失效,只要在erase时,递增当前的iterator即可。这是因为map之类的容器,使用了红黑树来实现,插入,删除一个结点不会对其他结点造成影响。使用方式如下例子:set<int> valset = { 1,2,3,4,5,6 }; set<int>::iterator iter; for (iter = valset.begin(); ite转载 2021-11-09 22:52:22 · 203 阅读 · 0 评论 -
C++ list::splice()函数
一、定义list::splice实现list拼接的功能。将源list的内容部分或全部元素删除,拼插入到目的list。函数有以下三种声明:void list::splice( iterator pos, list rhs );void list::splice( iterator pos, list rhs, iterator ix );void list::splice( iterator pos, list rhs, iterator first, iterator last );原创 2021-11-09 22:44:01 · 3127 阅读 · 1 评论 -
C++的分割字符串——strtok函数
一、介绍char *strtok(char *str, const char *delim)功能:作用于字符串str,以delim中的字符为分界符,将str切分成一个个子串,该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。二、实例实例一,分割字符串的基本用法,分割字符“-”,打印分割后的子字符串#include <string.h>#include <stdio.h> int main () { char str[80]原创 2021-11-06 21:45:08 · 4336 阅读 · 0 评论 -
C++ vector::assign的使用
一、assign函数介绍函数原型:void assign(const_iterator first,const_iterator last);void assign(size_type n,const T& x = T());功能:将区间[first,last)的元素赋值到当前的vector容器中,或者赋n个值为x的元素到vector容器中,这个容器会清除掉vector容器中以前的内容。二、实例 int main(int argc, char* argv[]) {原创 2021-11-06 14:01:50 · 13628 阅读 · 0 评论 -
C++中的++i 与 i++详解
一、区别i++ 与 ++i 的主要区别有两个:1、 i++ 返回原来的值,++i 返回加1后的值。2、 i++ 不能作为左值,而++i 可以。二、原理毫无疑问大家都知道第一点,我们重点说下第二点。首先解释下什么是左值(以下两段引用自中文维基百科『右值引用』词条)。左值是对应内存中有确定存储地址的对象的表达式的值,而右值是所有不是左值的表达式的值。一般来说,左值是可以放到赋值符号左边的变量。但是,能否被赋值不是区分左值与右值的依据。比如,C++的const左值是不可赋值的;而作为临时对转载 2021-10-30 22:36:44 · 8284 阅读 · 0 评论 -
__builtin_expect函数
一、背景在很多源码如Linux内核、Glib等,我们都能看到likely()和unlikely()这两个宏,通常定义如下#define likely(x) __builtin_expect(!!(x), 1)#define unlikely(x) __builtin_expect(!!(x), 0)可以看出这2个宏都是使用函数__builtin_expect()实现的,__builtin_expect()函数是GCC的一个内建函数(build-in function)...原创 2021-10-10 21:46:53 · 4050 阅读 · 0 评论 -
C++ std::function
std::function原创 2021-10-10 21:14:20 · 880 阅读 · 0 评论 -
C语言的va_list使用方法
一、定义在C++中又函数重载功能,C语言中也是又类似功能的,如经常见到的 int fun(char *format, ... ),该函数的参数个数是未定的,以此实现了类似重载的功能,我们用的最多的printf() 函数就是这样实现的,现在来讲讲这个怎么用:正如大家知道的那样,函数传入的参数是保存在栈中的,第一个参数在栈的最顶端,最后一个参数在栈的最底端,对于函数void fun(char *formt,...);进行调用fun("a","b","c","d","e","f","g");va_l..原创 2021-10-01 11:38:30 · 6744 阅读 · 0 评论