C++2.0常用特性
C++11常用特性
KingOfMyHeart
会好起来的.
展开
-
C++11 异步与通信之 std::async
std::async异步运行一个函数,将返回值保存在中。deferred延迟执行,当调用wait()和get()时,任务才会被运行,且不创建线程;async创建线程并执行任务,默认是此类型;同样的,调用get()方法获取对象时,也是阻塞等待的。原创 2023-08-13 22:03:48 · 563 阅读 · 0 评论 -
C++11异步与通信之 packaged_task
用于包装可调用目标(Callable)为一个对象,如lambda,普通函数,小括号重载等,用于异步调用。其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中,和promise类似。将函数的调用与函数返回值的获取分开调用,这样就给异步提供很大的便利。猛的一看好像和std::bind绑定器作用相似,可惜std::bind返回的对象是同步的。原创 2023-08-13 21:07:34 · 264 阅读 · 0 评论 -
C++11 异步与通信之promise and future
std::promise 只能使用一次, void set_value(T &&val)设置传递值,只能调用一次 (保证结果单一)std::promise提供存储异步通信的值,再通过其对象创建的std::future对象异步获得结果。一个函数在线程A中调用,函数调用的结果希望在线程B中获取,不直接使用锁和条件变量,如何简单的实现?调用get()阻塞等待 promise set_value(T &&val))设置的值。原创 2023-08-13 20:04:44 · 272 阅读 · 0 评论 -
C++11之条件变量 condition_variable
条件变量(condition_variable)是一种同步原语,用于线程之间的协调。它允许一个或多个线程一起等待另一个线程的通知。条件变量依赖于互斥量(mutex),它被用来保护等待条件变量的共享数据,并在条件满足时通知等待的线程。线程通过持有互斥锁来进入等待状态并等待从其它线程中获得信号释放,该线程可以获取到mutex。当其它线程以notify_one或notify_all的方式发出通知,等待线程被唤醒开始尝试重新获取互斥锁。这意味着只有在持有互斥锁时才可以进行等待或接收条件变量信号。原创 2023-08-13 19:33:26 · 381 阅读 · 0 评论 -
C++17 之 scoped_lock 死锁避免神器
用于多个互斥锁的免死锁 RAII 封装器,是一种更加灵活和安全的互斥量管理方式。是一种独占互斥锁,它可以同时锁定多个互斥锁,并保证以原子方式获得所有互斥锁,从而有效避免死锁。它可以接受多个互斥锁作为参数,并在构造函数中自动锁定这些互斥锁。当对象出作用域时,它会析构并自动解锁所有已经锁定的互斥锁,确保互斥访问的安全性和正确性。原创 2023-08-12 23:20:20 · 630 阅读 · 0 评论 -
C++14 17共享超时互斥锁 shared_timed_mutex / 共享锁 shared_mutex
共享锁,也叫。比如,在多线程环境下,多个线程操作同一个文件,其中读文件的操作比写文件的操作更加频繁,那么在进行读操作时,不需要互斥,线程间可以共享这些数据,随意的读取。但是一旦有写操作,那么一定要进行互斥操作,否则读取到的数据可能存在不一致。原创 2023-08-12 21:29:30 · 1380 阅读 · 0 评论 -
C++11 之 递归锁 recursive_mutex
在一些业务场景下,线程在获取锁后还会多次获取该锁,且保证不出现死锁或者程序崩溃异常。简单地说,递归锁是一种在。原创 2023-08-12 17:39:28 · 1247 阅读 · 0 评论 -
C++11之超时锁timed_mutex
超时锁:用来记录线程加锁 解锁 等竞争锁的过程,多用于调试多线程时使用。原创 2023-08-12 17:09:33 · 474 阅读 · 0 评论 -
C++使用mutex保护临界区时总是某一个线程在多次执行后才轮到下一个线程
记录一个有意思的现象,原创 2023-08-12 16:43:26 · 258 阅读 · 0 评论 -
详解C++特性之noexcept (C++11 C++17 C++20)
上面说到,noexcept()可以判断目标类型的移动构造函数是否可能抛出异常,那么我们可以先判断有没有抛出异常的可能,如果有,那么使用传统的复制操作,那么执行移动构造。实际上,这并不是最优解,因为很多自定义类型的拷贝构造也是很简单的,几乎不会抛出异常,我们还可以利用noexcept运算符的能力,判断类型的拷贝构造是否会抛出异常。判断类型是一个普通类型还是复杂的类型,如果是普通类型,返回true,则表示不会抛出异常,否则将表示可能会抛出异常。函数,则程序直接退出,否则跳转到处理异常的。在C++11前,使用。原创 2023-07-23 21:07:50 · 1649 阅读 · 0 评论 -
C++11之线程局部存储 thread_local
我们知道,在Linux系统中,子线程是通过复制来产生的,由于进程是资源分配的最小单位,那么,进程中的线程除了有自身运行时需要的一些栈空间,寄存器等资源,其余资源都是和其他线程共享的,这就会引入一些资源竞争的问题,为应用程序执行带来不确定性。而线程存储指的是一种特殊的内存机制,用于将数据存储在当前线程的私有内存中,这样线程就有自己私有的数据存储空间,不会被其他线程所干扰。实际上,线程局部存储早就出现,由于是一种特殊的内存机制,所以需要操作系统层面的支持。原创 2023-07-23 15:30:55 · 336 阅读 · 0 评论 -
C++中将thread_local变量的声明和定义分开
声明://Test.h#include <thread>extern thread_local int id;定义#include "Test.h"thread_local int id= 0;原创 2022-04-08 15:23:47 · 731 阅读 · 0 评论 -
新基础类型(C++11~C++20)
整数类型long longlong long该类型实际上我们很早就开始使用了,但是是直到C++11才加入标准中的;long一般表示一个32位的整型,long long一般表示64位的整型;long long是一个有符号的整型,对应无符号是unsigned long long;C++标准顶定义,long long至少是一个64位的整型,注意,这里是至少。定义是可以使用LL和ULL进行区分:long long a = 10000;long long b = 10ll;unsigned long原创 2021-10-31 14:53:11 · 791 阅读 · 0 评论 -
C++中vector的push_back()和emplace_back()区别
push_back()创建一个新元素,然后拷贝构造到容器的末尾。emplace_back()直接在容器尾部构造对象,直接调用构造函数进行构造,省去对象拷贝构造的过程。有案例的链接原创 2021-06-30 22:34:52 · 258 阅读 · 2 评论 -
c++中vector的clear(),swap()以及 shrink_to_fit()方法
clear()仅仅将容器中的元素释放(析构)掉,会导致size = 0,但是容器容量capacity不会变,即占用内存没有变化。int main(){ std::vector<int> vec; std::cout<<vec.size()<<std::endl; std::cout<<vec.capacity()<<std::endl; for(int i= 0;i < 10;++i) {原创 2021-06-30 20:43:03 · 1719 阅读 · 0 评论 -
C++11中lock_guard和unique_lock的特点和区别,condition_variable为何搭配unique_lock使用
lock_guardtemplate<typename _Mutex> class lock_guard { public: typedef _Mutex mutex_type; explicit lock_guard(mutex_type& __m) : _M_device(__m) { _M_device.lock(); } ~lock_guard() { _M_device.unlo原创 2021-06-20 22:56:05 · 1021 阅读 · 2 评论 -
c++面试题:实现一个简单的线程池
#include <memory>#include <functional>#include <thread>#include <iostream>#include <vector>class Thread{public: using ThreadFunction = std::function<void()>; Thread(ThreadFunction func,int id):func_(func)原创 2021-06-20 17:03:00 · 1522 阅读 · 0 评论 -
c++面试题:按照你对shared_ptr的理解,实现一个shared_ptr
#include <iostream>#include <unordered_map>#include <atomic>class Count{public: Count() =default; ~Count() = default; void Add(void *ptr) { ptr_map_[ptr] ++; } int Dec(void *ptr) { a原创 2021-06-20 17:01:43 · 333 阅读 · 0 评论 -
c++面试题:实现一个生产者消费者队列
#include <thread>#include <mutex>#include <condition_variable>#include <queue>#include <iostream>class Queue{public: void Put(int val) { std::unique_lock<std::mutex> lck(mtx_); //队列不为空,通知原创 2021-06-20 17:00:00 · 1087 阅读 · 1 评论 -
除了加锁还可以这样写一个线程安全的单例模式(局部静态对象和std::call_once)
1. linux x86平台上局部静态对象构造是线程安全的class Singleton{public: static Singleton*GetInstance(){ //函数静态局部变量的初始化,汇编指令上已经自动添加了互斥指令了,所以这里是线程安全的 static Singleton instance; return &instance; }private: Singleton(){} Singleton(c原创 2021-04-30 23:09:28 · 233 阅读 · 2 评论 -
使用std::make_shared去构造智能指针
class Test{public: Test(int b):a(b){} ~Test(){}private: int a;};用std::shared_ptr管理资源时,常用的两种构造方式:1.直接newint main(){ std::shared_ptr<Test> p(new Test(1)); return 0;}2.使用std::make_shared:int main(){ std::shared_ptr<原创 2021-04-30 22:18:03 · 1642 阅读 · 1 评论 -
C++11判断一个函数对象std::function是否可调用operator bool()
判断一个函数对象是否可调用: operator bool()返回true证明对象可调用#include <functional>#include <iostream>using Task = std::function<void()>;template<typename T>void CallTaskFunc(const T&f){ if(f.operator bool()){ f(); }else{原创 2021-04-30 21:57:16 · 1483 阅读 · 1 评论 -
C++11中is_same使用
使用场景:我们在写模板代码时,希望对于某些类型做不同处理,需要对实参类型进行一个判断,std::is_same是个不错的选择。实例:假如,用户用int类型去实例化该模板,我希望做一些特殊操作,代码可以这样写:#include <iostream>#include <type_traits>template <typename T>void fun(T a){ if(std::is_same<T,int>::value){原创 2021-04-30 21:20:37 · 1864 阅读 · 1 评论 -
模板特例化与偏特化
模板是C++中一个很重要的特性,写一份代码能用于多种数据类型(包括用户自定义类型)。例如,STL的sort()函数可以用于多种数据类型的排序,类stack可以用作多种数据类型的栈。但是,如果我们想对特定的数据类型执行不同的代码(而不是通用模板)呢?这种情况下就可以使用模板特例化(template specialization)。一、函数模板特例化当特例化一个函数模板时,必须为原模板中的每个模板参数都提供实参。使用关键字template后跟一个空尖括号<>,即template <>转载 2021-04-29 22:21:36 · 428 阅读 · 0 评论 -
c++11中shared_from_this的使用情景与案例
class C{public: C(int b=10):a(b){ cout<<"construct"<<endl; } ~C(){ cout<<"destruct"<<endl; } void show()const{ cout<<"a = "<<a<<endl; } C*object_ptr(){ return this; }private: int a;};使用场景:原创 2021-04-29 22:06:09 · 4342 阅读 · 1 评论 -
记录几个C++智能指针shared_ptr常用方法
#include <memory>#include <iostream>using namespace std;class Test{public: Test(int b=10):a(b){ cout<<"construct"<<endl; } ~Test(){ cout<<"destruct"<<endl; } void show()const{ cout<<"a = "<<a原创 2021-04-29 21:28:39 · 151 阅读 · 0 评论 -
c++多线程运行错误:terminate called without an active exception(运行错误)
创建线程以后,主线程没有等待子线程一起退出,应该由子线程调用join()。原创 2020-04-16 20:22:15 · 3236 阅读 · 0 评论 -
传递类对象以及智能指针作为线程参数(以detach()结尾)
结论:当传递一个类对象作为线程参数时,不论是用字面值接受,还是用引用接受,thread()都会将这个对象拷贝一份,所以我们在线程函数中修改这个对象,没法对主线程中的对象产生影响.一.线程idstd::this_thread::get_id():获取线程id二.经验thread()+detach():给子线程传递参数时,使用临时对象作为参数,子线程函数的参数在主线程退出前构造出来,最后...原创 2019-07-20 16:32:33 · 1770 阅读 · 0 评论 -
detach收尾时传递临时对象作为线程参数
线程传参detach()成员函数做线程函数一.传递临时对象作为线程参数原创 2019-07-20 13:59:54 · 451 阅读 · 0 评论 -
C++11多线程中的detach()、join()、joinable()
一.传统多线程编写:一般来说,我们在主线程中开辟出一些子线程来完成我们的任务,正常情况下,需要在主线程的最后调用join(),用于阻塞主线程,避免主线程先于其他子线程执行完毕,退出,然后导致整个进程的异常.join():阻塞主线程,等待其他子线程执行完毕,正常退出.二.非传统多线程编写: 引入detach()有人说,我们创建多个线程完成一些任务,不过需要主线程最后等待所有的子线程完毕才能...原创 2019-07-19 16:21:02 · 6893 阅读 · 0 评论 -
使用各种可调用方法进行线程的创建(lambda、class operator()...)
一.单核CPU和多核CPU:单核:每一时刻只能有一个任务进行运算,至于那个任务进行运算,由操作系统调度算法等决定(“并发假象”),宏观意义上的并发;缺点:每次不同任务进行切换,实际上是切换的是任务的上下文,以及任务之前的CPU上进行运行的时候也会把CPU旁边的cache数据切换,这个开销也是很大的,包括将一个进程数据从磁盘引入内存,调度运行都是很大的开销多核:真正的并行任务(硬件并...原创 2019-07-19 16:58:17 · 259 阅读 · 0 评论 -
使用C++11多线程模拟多窗口售票出现的常见问题分析总结以及最终解决方案
1. 单线程(单窗口)卖票static int Count = 100;void SellTicket() { while (Count > 0) { Count--; }}如果在单线程环境下,该方法永远不会出错,因为不会产生竞态条件,那么什么是竞态条件。2. 竞态条件多线程环境中,无论线程如何随着调度算法的不同产生不同的执行顺序,运行结果总能保持一致性。3.1 第一个多线程版本:锁加到循环外边static int Count = 100;std::mutex tex;原创 2020-08-08 15:23:18 · 947 阅读 · 0 评论 -
右值引用
回顾C98:在C++98的标准中的引用叫做左引用,也就是左值的引用,本质上是一个指针.左值引用的一般使用: int a =9; int &b = a;那既然叫左值引用,自然不能随意引用右值,如果要引用右值,需要使用常引用.常引用:const int &c = 99;类与对象中的常引用的使用://类外实现 拷贝构造函数CGoods :: CGo...原创 2019-08-19 19:09:47 · 247 阅读 · 0 评论 -
C++11新语法之=delete、=default
1. 相关知识点盘点如果我们不去给一个类实现构造函数,那么编译器会给我们实现一个什么都不做的空构造;如果我们不去给一个类实现析构函数,那么编译器会给我们实现一个什么都不做的析构函数;如果我们不希望外部使用一个接口,最常见得手法是将其私有化。2. =delete :删除一个函数,删除后函数将无法被使用这里假设,我们需要一个不能在堆上构造对象的类,那么就需要将new和delete运算符重载禁用掉:1.将new和delete运算符重载重载私有化,那么用户无法构造;class foo {public原创 2020-08-02 17:43:07 · 356 阅读 · 0 评论 -
C++11新语法之继承构造函数
1. 回忆继承我们知道,在C++的继承体系中,子类继承父类时,会将父类除了构造函数和析构函数以外的所有数据都继承下来。子类中如果有与父类名字相同的方法,子类将隐藏父类方法,优先使用子类方法。划重点:子类继承不会继承父类的构造和析构函数,同名方法会被子类隐藏。2. 继承构造函数语法:using Base::Base正因为子类没法继承父类的构造函数,所以我们在C++11之前,需要在子类的初始化列表中显式的调用基类的构造函数或者默认构造函数。基类,有三个构造函数的重载版本:class Base{p原创 2020-08-02 16:52:55 · 1326 阅读 · 0 评论 -
C++11新语法之std::bind简介与使用
#include <vector>#include <iostream>#include <algorithm>#include <functional>#include <string>void Fun1(){ std::cout<<"Call Fun1()"<<std::endl;}int...原创 2020-08-02 16:22:21 · 1607 阅读 · 1 评论 -
C++11新语法之委托构造函数
1. 委托构造函数的使用场景在实际的开发中,为了满足不同用户的不同需求,我们的一个类可能会有很多构造函数的重载版本,特别的,这些重载版本的工作内容有的比较复杂,有的比较简单,并且他们之间会有一些交叉重复的工作,即一些代码、或者数据的初始化在每个构造函数中都会去写一遍,这样显得代码特别的臃肿丑陋,委托构造函数应运而生。2. 使用委托构造函数实例:允许在一个构造函数的初始化列表中调用另外一个构造函数,委托另外一个构造函数进行一些初始化工作2.1 在没法进行委托构造时我们的code可能是这样的:class原创 2020-08-01 17:09:42 · 801 阅读 · 0 评论 -
C++11新增关键字override
1. C++中常见的成员方法的关系重载 overload : 在同一作用域下,函数名相同,参数列表不同,构成重载隐藏 overhide :在继承体系中,子类中方法与父类方法的名称一样,在子类中,会将父类的同名方法隐藏重写 override : 在继承体系中,子类重新实现父类的虚函数为己所用,(函数名和参数列表形同)2. C++11中新增override关键字:增强代码可读性,显式的告诉编译器我这个方法覆盖的是子类的某个虚函数,也防止程序员疏忽class Base {public:原创 2020-08-01 16:14:51 · 660 阅读 · 0 评论 -
C++11新增关键字final
看到这个关键字大家很容易的能将它翻译成为最终的,不可更改的。是的,这个字在我们C++代码中也是这意思,用在继承体系中,修饰类或者修饰基类中的虚函数。1. 修饰类:表示这个类是最终的,不能被其他类继承,也就不能被改写了//被final修饰的类class Base final{public: Base(int data) :ma(data) { cout << "Base(int data)" << endl; mc = data; } Base() = def原创 2020-08-01 15:43:31 · 298 阅读 · 0 评论 -
Lambad表达式使用以及原理
1.构成lambad表达式的几个重要部分lambad表达式的形式:[]()->return_type {}[ ]:捕获外部变量;[]:不捕获任何外部变量[=]:以传值的方式捕获外部变量[&]:以传引用的方式捕获外部变量[this]:如果是在类的成员方法中的话,可以捕获this指针[=,&a]:a以引用的方式捕获,其他都以值传递的方式进行捕获[a,&b]:a以传值的方式进行捕获,b以传引用的方式进行捕获():lambad表达式的参数列表;->原创 2020-07-23 21:00:56 · 968 阅读 · 0 评论