首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C++ 11原子和侵入式共享指针引用计数

C++ 11提供了对原子和共享指针的支持,这使我们可以创建高度并发和同步的代码。原子是C++ 11中的一种同步机制,用于在多线程环境中对共享内存进行原子操作。侵入式共享指针是一种新的共享指针风格,它可以在多线程环境中安全地更新共享指针的引用计数。

原子 (Atomic)

原子操作是在多线程环境中对共享内存进行操作的一种同步机制。C++ 11提供了std::atomic模板类,用于创建原子对象,这些对象可以进行修改,并且在多线程环境中保证其原子性。

代码语言:cpp
复制
#include <iostream>
#include <atomic>

std::atomic<int> counter(0);

void increment() {
    counter.fetch_add(1);
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    t1.join();
    t2.join();
    std::cout << counter << std::endl;
    return 0;
}

侵入式共享指针 (Shared Pointer)

侵入式共享指针是一种新的共享指针风格,它允许在多线程环境中安全地更新共享指针的引用计数。C++ 11提供了std::shared_ptr模板类,它具有自动计数和避免循环引用带来的内存泄漏问题。

代码语言:cpp
复制
#include <iostream>
#include <shared_ptr>

class MyClass {
public:
    MyClass() { std::cout << "MyClass 构造函数" << std::endl; }
    ~MyClass() { std::cout << "MyClass 析构函数" << std::endl; }
};

int main() {
    std::shared_ptr<MyClass> obj1(new MyClass());
    std::shared_ptr<MyClass> obj2 = obj1;
    std::cout << "obj1 的引用计数: " << obj1.use_count() << std::endl;
    std::cout << "obj2 的引用计数: " << obj2.use_count() << std::endl;
    return 0;
}

引用计数 (Reference Counting)

C++ 11提供了std::shared_ptrstd::weak_ptr模板类,这些类可以自动管理对象的引用计数。弱指针(std::weak_ptr)不能直接访问对象,但可以在多个强指针之间创建一个弱指针,用于解决循环引用问题。

代码语言:cpp
复制
#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() { std::cout << "MyClass 构造函数" << std::endl; }
    ~MyClass() { std::cout << "MyClass 析构函数" << std::endl; }
};

int main() {
    std::shared_ptr<MyClass> obj1(new MyClass());
    std::shared_ptr<MyClass> obj2 = obj1;
    std::cout << "obj1 的引用计数: " << obj1.use_count() << std::endl;
    std::cout << "obj2 的引用计数: " << obj2.use_count() << std::endl;

    // 创建一个弱指针,用于解决循环引用问题
    std::weak_ptr<MyClass> obj3 = obj1;

    if (obj3.expired()) {
        std::cout << "obj3 已过期, 无效" << std::endl;
    } else {
        std::shared_ptr<MyClass> obj3_shared = obj3.lock();
        std::cout << "obj3 的引用计数: " << obj3_shared.use_count() << std::endl;
    }

    return 0;
}

总之,C++ 11提供了原子和共享指针,使得我们可以创建高度并发和同步的代码,而无需使用繁琐的锁机制。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++ 共享指针四宗罪

本文主要针对基于boost::shared_ptr的C++引用计数实现方案进行一些讨论。C++引用计数方案往往伴随着用于自动管理引用计数的智能指针。...按是否要求资源对象自己维护引用计数C++引用计数方案可以分为两类: 侵入侵入引用计数管理要求资源对象本身维护引用计数,同时提供增减引用计数的管理接口。...通常侵入方案会提供配套的侵入引用计数智能指针。该智能指针通过调用资源对象的引用计数管理接口来自动增减引用计数。COM对象与CComPtr便是侵入引用计数的一个典型实例。...非侵入:非侵入引用计数管理对资源对象本身没有任何要求,而是完全借助非侵入引用计数智能指针在资源对象外部维护独立的引用计数。shared_ptr便是基于这个思路。...一次拷贝就对应一对引用计数原子增减操作。 对于上述的可优化资源对象,如果在一个流程中被传递3次,除去分配释放时的2次,还会导致6次无谓的原子整数操作。整整浪费了300%!

52350

TarsCpp 组件 之 智能指针详解

auto_ptr 在 C++98 中提出,但其不能共享对象、不能管理数组指针,也不能放在容器中。因此在 C++11 中被摒弃,并提出 unique_ptr 来替代,支持管理数组指针,但不能共享对象。...计数采用的是 C++ 标准库 中的原子计数类型 std::atomic。 计数的实现封装在类 TC_HandleBase 中,开发者无需关注。...原子计数类 std::atomic std::atomic 在 C++11 标准库 中定义。...TARS 智能指针模板类 TC_AutoPtr 提供引用计数的相关操作,增加计数减少计数接口的相关代码如下 可以看到,这里通过整型的原子计数类的对象 _atomic 实现引用计数,管理智能指针指向对象的引用计数...-1`; • 析构函数:引用计数 `-1`; TC_AutoPtr 优势 经过上述分析,可以发现 `TC_AutoPtr` `shared_ptr` 在用法功能上非常相似,都支持多个指针共享一个对象

92220
  • C++智能指针

    6、std::weak_ptr 7、删除器 8、C++11boost中智能指针的关系 零、前言 本章主要讲解学习C++中智能指针的概念及使用 一、为什么需要智能指针 示例: double Division...由于资源共享,需要使用引用计数,也就是计数也是共享的,那么对计数的操作需要保证原子性,否则会造成数据混乱 示例: int main() { // shared_ptr通过引用计数支持智能指针对象的拷贝...mutex* _mtx;//多线程互斥 //堆上开辟-多个智能指针共享计数互斥锁 }; shared_ptr的线程安全分为两方面: 智能指针对象中引用计数是多个智能指针对象共享的,引用计数同时...mutex* _mtx;//多线程互斥 //堆上开辟-多个智能指针共享计数互斥锁 }; 注:这里的模拟并不一定就是C++中真真的底层实现 8、C++11boost中智能指针的关系...C++ 98 中产生了第一个智能指针auto_ptr C++ boost给出了更实用的scoped_ptrshared_ptrweak_ptr C++ TR1,引入了shared_ptr等。

    60520

    彻底搞懂之C++智能指针

    直至所有 shared_ptr 所有者超出了范围或放弃所有权,才会删除原始指针。 大小为两个指针;一个用于对象,另一个用于包含引用计数共享控制块。 头文件:。...所有实例均指向同一个对象,并共享对一个“控制块”(每当新的 shared_ptr 添加、超出范围或重置时增加减少引用计数)的访问权限。 当引用计数达到零时,控制块将删除内存资源自身。...parent Object id:11 weak_ptr weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针引用计数永远不可能下降为...如果内存仍有效,新的共享指针会递增引用计数,并保证只要 shared_ptr 变量保持在范围内,内存就有效。...因为除了要管理一个裸指针外,还要维护一个引用计数。 因此相比于 unique_ptr, shared_ptr 的内存占用更高 原子操作性能低 考虑到线程安全问题,引用计数的增减必须是原子操作。

    3.6K10

    C++智能指针的正确使用方式

    博客: www.cyhone.com 公众号:编程沉思录 --- C++11中推出了三种智能指针,unique_ptr、shared_ptrweak_ptr,同时也将auto_ptr置为废弃(deprecated...性能 因为C++的zero cost abstraction的特点,unique_ptr在默认情况下指针的大小是一样的。 所以内存上没有任何的额外消耗,性能是最优的。...而w2获得了对象所有权,但因为此时w已不再持有对象,因此w2的引用计数为1。 性能 内存占用高 shared_ptr的内存占用是裸指针的两倍。因为除了要管理一个裸指针外,还要维护一个引用计数。...因此相比于unique_ptr, shared_ptr的内存占用更高 原子操作性能低 考虑到线程安全问题,引用计数的增减必须是原子操作。而原子操作一般情况下都比非原子操作慢。...存在着循环引用,根据shared_ptr引用计数的原理,papb都无法被正常的释放。

    9.9K42

    C++】智能指针

    2、智能指针发展史 C++ 中的第一个智能指针名为 auto_ptr,由 C++98 提供,但由于 auto_ptr 存在极大的缺陷,同时 C++98 的后一个大版本 – C++11 又发布的很晚,所以...boost 库中提供了另外的几种重要的智能指针 – scoped_ptr、shared_ptr weak_ptr,它们都被 C++11 标准所借鉴,并发布了对应的标准版本 – unique_ptr、...而库中的 shared_ptr 的引用计数之所以是线程安全的,是因为它使用了 互斥锁 对引用计数的 ++ – 操作进行了保护,即通过加锁使得多线程只能串行的修改引用计数的值,而不能并行或并发的修改引用计数...我们也可以使用互斥锁将模拟实现的 shared_ptr 改造为引用计数线程安全版本,需要注意的是: 引用计数一样,使用互斥锁的方式也是在类中增加一个互斥锁指针类型的成员变量,该变量指向堆上的一块空间;...n1、n2 自动销毁,则资源1资源2的引用计数分别减为1,而当引用计数为0时资源才会释放,所以发生内存泄露。

    19330

    京东面经(含答案)

    原子变量volatile区别(C++11) Volatile变量可以确保先行关系,即写操作会发生在后续的读操作之前, 但它并不能保证原子性。...智能指针介绍(C++11) 1.auto_ptr主要是用来解决资源自动释放的问题;auto_ptr支持赋值复制,将指针的所有权转移,但是如果转移后再访问原来得指针,行为不确定,程序可能会在运行时出错。...但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。同样,在weak_ptr析构时也不会导致引用计数的减少,它只是一个静静地观察者。...weak_ptr 没有重载operator*->,这是特意的,因为它不共享指针,不能操作资源,这是它弱的原因。...智能指针内部实现(C++11) 智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针

    84510

    UE4智能指针

    ,有一个指针指向控制块 shared_ptr相当 为什么使用UE4的智能指针而不是用c11的(两个做具体的对比) 所有编译器和平台上有更加一致的实现 可以虚幻本身的类型更好的结合,比如容器等...基本裸指针相同 TSharedPtr 引用计数的非侵入的权威智能指针 默认是裸指针两倍,但是多出了控制块的内存 有一定的内存消耗,大约是两倍 TSharedRef 引用计数的非侵入的权威智能引用...(只是不能为null) 同上 同上 TWeakPtr 引用计数的、非侵入指针引用 两倍的裸指针大小,有一个指针指向控制块 比Tsharedptr略慢 - 所有共享指针的内存消耗(...8字节)(32位系统) - 源指针(32位) - 引用控制器(32位) - 应用控制器(12字节) - 源指针 - 共享引用计数 - 弱引用计数使用的方法(以TSharedPtr...TSharedRef - 共享引用 --- 使用引用计数的不允许为空的智能指针.

    7K71

    千万不要错过的后端【纯干货】面试知识点整理 I I

    ,shared_ptr使用引用计数(use_count方法),每个shared_ptr的拷贝都指向同一块内存,在最后一个shared_ptr被析构的时候,内存才会被释放 shared_ptr 是引用计数的方式...next 存在循环引用,他们的引用计数都变为 2 出了作用域之后,cur next 被销毁,引用计数减 1 因此要释放cur , 就需要释放next 的 _pre,要释放next , 就需要释放cur...的 _next 内存泄漏检测工具 valgrind内存检测工具 valgrind的官方网址是:http://valgrind.org valgrind被设计成非侵入的,它直接工作于可执行文件上,...shmdt 分离共享内存 shmctl 控制共享内存 c++ STL内存优化 c++11新特性: 关键字语法 auto关键字 编译器可以根据初始化来推导数据类型,不能用于函数传参以及数组类型推导...函数指针的好处作用: 好处:简化结构程序通用性的问题,也是实现面向对象编程的一种途径 作用: 实现面向对象编程中的多态性 回调函数 inline函数与宏定义 inline函数是C++引入的机制

    79630

    重温 CC++ 笔记

    = delete 表示明确禁用某个函数(非构造、析构也可以用),让外界无法调用 C++ 有隐构造转型的规则。 隐类型转换:类型 A 被自动转成表达式需要的类型 B。...指针是内存地址,引用是变量别名,指针可以是空,而引用不能为空(引用必须初始化,否则编译失败) 引用是通过指针常量实现的 指针完全映射了计算机硬件,操作效率高,是 C++ 效率高的根源。...unique_ptr 独占使用的指针,不能直接赋值给其他指针,需要通过右值转移,转移后之前指针变成空指针 make_unique() shared_ptr 共享使用的指针 内部使用了引用计数,use_count...可以查看有几个引用引用为 0 时,才会 delete 内存 make_shared() 还可以定制内存删除函数 缺点: 引用计数的存储管理都是成本 在运行阶段,引用计数的变动很复杂,很难知道它真正释放资源的时机...gperftools 是“侵入的性能分析工具,能够生成文本或者图形化的分析报告,最直观的方式是火焰图。

    1.3K30

    智能指针:作用 | 使用 | 原理 | 内存泄漏

    ,用指针实现 }; } 线程安全问题 智能指针对象本身拷贝析构是线程安全的,底层引用计数加减是安全的,指向的资源访问不是线程安全的(该加锁需要加锁) 智能指针对象中引用计数是多个智能指针对象共享的,两个线程中智能指针引用计数同时...++或--,这个操作不是原子的,引用计数原来是1,++了两次,可能还是2.这样引用计数就错乱了。...所以只能指针引用计数++、--是需要加锁的,也就是说引用计数的操作是线程安全的。...C++11boost中智能指针的关系 C++ 98 中产生了第一个智能指针auto_ptr. C++ boost给出了更实用的scoped_ptrshared_ptrweak_ptr....C++ TR1,引入了shared_ptr等。不过注意的是TR1并不是标准版。 C++ 11,引入了unique_ptrshared_ptrweak_ptr。

    11110

    c++】智能指针详解&&c++特殊类设计&&c++的类型转换

    需要注意的是shared_ptr的线程安全分为两方面: 智能指针对象中引用计数是多个智能指针对象共享的,两个线程中智能指针引用计数同时++或--,这个操作不是原子的,引用计数原来是1,++了两次,可能还是...: node1node2两个智能指针对象指向两个节点,引用计数变成1,我们不需要手动delete node1的_next指向node2,node2的_prev指向node1,引用计数变成2 node1...node2析构,引用计数减到1,但是_next还指向下一个节点。...node1;时weak_ptr的_next // _prev不会增加node1node2的引用计数。...C++11boost中智能指针的关系 C++ 98 中产生了第一个智能指针auto_ptr C++ boost给出了更实用的scoped_ptrshared_ptrweak_ptr C++ TR1

    11910

    7 种单例模式实现方法大揭秘:从饿汉到Meyers Singleton

    单例模式可以保证系统中只有一个实例存在,避免了多次实例化造成的资源浪费不一致性问题。通过单例模式,其他对象可以直接访问单例对象,提供了一种方便的全局访问方式,简化了对象之间的通信和数据共享。...单例模式可以方便地实现对共享资源的集中管理,确保资源的线程安全性。控制实例化过程:单例模式可以控制实例化过程,例如延迟实例化、懒加载等,提升系统的性能效率。...三、懒汉(Lazy initialization)C++中的懒汉(Lazy Initialization)是一种延迟加载的单例模式实现方式。...但需要注意,双重检查锁定在C++11之前可能存在一些细微的问题,因为编译器可能会对代码进行优化,导致内存读写顺序不一致。可通过设置合适的内存屏障或使用原子操作等技术来解决这个问题。...接下来的每次调用都会返回同一个共享指针,这样可以确保只有一个实例被创建和共享。std::shared_ptr 使用引用计数的方式管理内存,当没有任何指针引用该对象时,内存会自动释放。

    19610

    Rust避坑现代C++悬垂指针

    开启现代C++的C++11引入了unique_ptr、shared_ptrweak_ptr等智能指针。unique_ptr采用严格的所有权语义,保证对象只被单个指针所有。...shared_ptr采用引用计数,允许共享所有权。weak_ptr不影响引用计数,用于解决shared_ptr的循环引用问题。配合移动语义、完美转发等特性,大大减少了悬垂指针问题。...C++赋予程序员极大的灵活性,是极富影响力的编程语言。C++自C++11以来引入了智能指针,提供了自动内存管理的能力,这在一定程度上减少了内存泄漏悬垂指针等问题的发生。...使用引用计数来跟踪有多少个shared_ptr共享同一个对象。当最后一个指向对象的shared_ptr被销毁时,对象会被删除。shared_ptr适用于以下场景。需要在多个对象间共享资源。...Box:用于在堆上分配值Rc:引用计数智能指针,允许多个所有者共享同一数据的不可变所有权Arc:原子引用计数智能指针,用于在并发场景下以不可变访问来避免数据竞争Cell:提供内部可变性

    53361

    【重学C++】02 脱离指针陷阱:深入浅出 C++ 智能指针

    乐于分享的shared_ptrshared_ptr是C++11提供的另外一种常见的智能指针,与unique_ptr独占对象方式不同,shared_ptr是一种共享智能指针,允许多个shared_ptr...shared_ptr共享一个资源对象,例如std::shared_ptrp3 = p2;shared_ptr采用引用计数的方式管理资源对象的生命周期,通过分配一个额外内存当计数器。...否则,将计数指针置为nullptrshared_ptr使用注意事项避免循环引用由于 shared_ptr 具有共享同一个资源对象的能力,因此容易出现循环引用的情况。...,利用weak_ptr不会增加shared_ptr的引用计数的特点,我们将Node.next的类型改为weak_ptr, 避免node1node2互相循环引用。...unique_ptr用于管理独占所有权的对象,它不能拷贝但可以移动,是最轻量级最快的智能指针。shared_ptr用于管理多个对象共享所有权的情况,它可以拷贝移动。

    40400

    论golang是世界上最好的语言

    c + +由于存在指针计算,即p++、p--等,无法提供垃圾回收功能,而golang虽然有指针,但是舍弃了指针的++、--等操作,所以提供了垃圾回收功能。...封装 封装这一块,可以细分为封装+隐藏: (1) 封装:将数据基于数据的操作封装在一起,在C++中,通过隐藏的this指针传递对象的地址,在C中,要实现封装,要显传递,在golang中,与C类似,显传递...5、并发编程 不要通过共享内存来通信,而应该通过通信来共享内存 golang是为并发而生的语言,goroutine+channel使得并发编程变得容易。...当然,golang依然提供了各种同步互斥机制,与CC++不同的是,golang对这些机制都做了封装: 管道 ①匿名管道 ②命名管道,基于文件的,有原子性问题 ③基于内存的,有原子性操作保证的管道 信号...强制要求显类型转换: 隐类型转换造成的问题远大于带来的好处,所以go强制要求使用显类型转换,加上不支持操作符重载,所以我们总是能够确定语句表达式的明确含义。

    1.6K90

    lockfree 的队列的实现

    上面是用两个数来记录开始结束的下标,我觉得用两个指针也可以。...另外还有一个改进是使用引用计数,管理下内存,免得一个节点被重复释放或加入,对于引用计数的加减就只能用下原子函数来保证原子性了,下文提到的ABA 的问题,个人觉得也就只有在内存被重复释放或添加时有影响,所以引用计数是个比较好的方案...还有提一下的是如果使用C++11中的 STL 中的 atomic 类的函数可以跨下平台,不用的人自己加些宏定义也可以,没什么特别的,说是无锁其实也就是应用层的无锁,使用了下原子操作来进行很小颗粒的锁操作...,这样明确的业务问题比较好解决,论文《Implementing Lock-Free Queues》给出一这么一个方法——使用结点内存引用计数 refcnt!...Release 分是是加引用计数引用计数,都是原子操作,这样就可以阻止内存被回收了。

    39820

    C++C++的内存处理 --- 智能指针

    get:获取到智能指针内部的指针! release:显释放空间! -> *:支持的指针操作! shared_ptr支持所有的构造,包括拷贝构造!其引入了引用计数的概念(Linux中很常见)!...首先我们分析一下临界区,在share_ptr中引用计数是临界的!为什么呢?因为引用计数的操作++ -- 是非原子的!多个线程中我们不断进行copy拷贝,会对引用计数不断进行++--,导致了问题!...为了从根本上解决这个问题,我们就要保证操作是原子的!我们可以在类中加入一个锁来保证++--中进行保护。但是最直接的就是将引用计数变成原子的就可以了!...//引用计数 std::atomic* _pcount; 这样就可以保证拷贝析构的时候就是原子的了就不会出现问题了!!!就可以保证线程安全了!...对于C++来说,内存泄漏是很严重的问题!C++没有JAVA的垃圾回收机制。

    13110
    领券