吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1366|回复: 9
收起左侧

[C&C++ 原创] C++智能指针的原理及其线程安全性

  [复制链接]
licks 发表于 2024-6-19 23:04

在C++中,智能指针是一种用于自动管理动态内存的对象,目的是避免手动管理内存带来的错误,如内存泄漏和悬挂指针。C++标准库中主要提供了三种智能指针:std::unique_ptr、std::shared_ptr和std::weak_ptr。以下是它们的原理和使用示例。

std::uniqueptr
原理: std::unique_ptr 是一种独占所有权的智能指针,保证同一时刻只能有一个智能指针拥有对象的所有权。它在指针被销毁时自动删除所指向的对象,避免了内存泄漏。

实现原理:

1.所有权独占:不能复制,但可以移动。即一个unique_ptr对象不能被赋值给另一个unique_ptr对象,但可以通过std::move函数将所有权转移。
2.析构函数:当unique_ptr对象被销毁时,其析构函数会自动调用delete释放所持有的资源。
示例:

#include <iostream>
#include <memory>

int main() {
    std::unique_ptr<int> ptr1(new int(10));
    std::cout << *ptr1 << std::endl;

    // std::unique_ptr<int> ptr2 = ptr1; // 错误:不能复制
    std::unique_ptr<int> ptr2 = std::move(ptr1); // 转移所有权
    std::cout << *ptr2 << std::endl;

    // ptr1现在为空
    if (!ptr1) {
        std::cout << "ptr1 is empty" << std::endl;
    }

    return 0;
}

线程安全性:

unique_ptr是一个独占所有权的智能指针,同一时间只能有一个std::unique_ptr指向一个对象。

*非共享所有权:*std::unique_ptr本质上不支持共享所有权,因此不能在多个线程中共享。同一时间只能有一个std::unique_ptr指向一个对象,这意味着你不能在多个线程中共享和修改同一个std::unique_ptr实例。
转移所有权的线程安全:**std::unique_ptr的所有权转移操作(例如std::move)在单线程环境中是安全的,但在多线程环境中需要额外的同步来保证线程安全。例如:

std::unique_ptr<int> p = std::make_unique<int>(10);
// 在多个线程中同时执行以下操作是不安全的
std::unique_ptr<int> p2 = std::move(p);

std::sharedptr
原理: std::shared_ptr 是一种共享所有权的智能指针,多个shared_ptr可以指向同一个对象,使用引用计数来跟踪有多少个shared_ptr指向同一个对象。当最后一个shared_ptr销毁时,所指向的对象会被自动删除。

实现原理:

1.引用计数:每个shared_ptr都维护一个引用计数,当shared_ptr被复制时,引用计数增加;当shared_ptr被销毁时,引用计数减少。
2.控制块:每个对象都有一个控制块,包含引用计数和资源管理信息。当引用计数变为0时,控制块负责释放对象。
示例:

#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(10);
    std::shared_ptr<int> ptr2 = ptr1; // 共享所有权

    std::cout << *ptr1 << std::endl;
    std::cout << *ptr2 << std::endl;

    std::cout << "Use count: " << ptr1.use_count() << std::endl;

    return 0;
}

线程安全性:

shared_ptr是一个引用计数的智能指针,多个std::shared_ptr可以共享同一个对象。当最后一个std::shared_ptr销毁时,所管理的对象也会被销毁。

*引用计数的线程安全:引用计数的增加和减少是线程安全的。也就是说,不同的线程可以安全地复制或销毁std::shared_ptr,引用计数的变化是原子的,不会导致竞争条件。例如,以下操作在多线程环境中是安全的:

std::shared_ptr<int> p1 = std::make_shared<int>(10);
std::shared_ptr<int> p2 = p1; // 引用计数增加,线程安全
p1.reset(); // 引用计数减少,线程安全

*读取底层对象的线程安全:如果多个线程只读访问共享对象,是安全的。例如,以下代码是线程安全的:

auto sp = std::make_shared<int>(10);
// 在多个线程中读取 *sp 是安全的

*修改底层对象的线程安全:如果多个线程要修改共享对象,需要使用额外的同步机制(如互斥锁)来确保线程安全。std::shared_ptr本身并不提供对底层对象的写操作的同步。
虽然引用计数的修改是线程安全的,但访问或修改std::shared_ptr本身的值(即改变它指向的对象)需要同步。例如:

std::shared_ptr<int> p = std::make_shared<int>(10);
// 在多个线程中同时执行以下操作是不安全的
p = std::make_shared<int>(20);

std::weakptr
原理: std::weak_ptr 是一种不控制对象生命周期的智能指针。它与std::shared_ptr配合使用,用于解决循环引用的问题。weak_ptr可以观测对象的存在,但不会影响对象的生命周期。

实现原理:

1.弱引用:weak_ptr不会增加引用计数。它只能从shared_ptr创建,并且只能转化为shared_ptr使用。
2.检查有效性:可以通过expired方法检查对象是否已被销毁,通过lock方法获取指向对象的shared_ptr。
示例:

#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> sptr = std::make_shared<int>(10);
    std::weak_ptr<int> wptr = sptr; // 创建弱引用

    if (auto spt = wptr.lock()) { // 获取shared_ptr
        std::cout << *spt << std::endl;
    } else {
        std::cout << "Object no longer exists" << std::endl;
    }

    sptr.reset(); // 释放对象

    if (wptr.expired()) {
        std::cout << "Object no longer exists" << std::endl;
    }

    return 0;
}

总结
智能指针通过自动管理内存,避免了常见的内存管理问题,使C++编程更加安全和高效。不同类型的智能指针适用于不同的场景:

*std::unique_ptr适用于独占资源的场景。
*std::shared_ptr适用于共享资源的场景。
*std::weak_ptr用于解决循环引用问题并观测资源。
理解智能指针的工作原理和使用场景,是掌握现代C++编程的重要一步。
线程安全性的总结:
*std::shared_ptr:*引用计数的增加和减少是线程安全的,但对底层对象的访问和修改需要同步。
std::unique_ptr:**本质上是非共享的,不能在多个线程中同时使用同一个std::unique_ptr实例。所有权转移需要同步。
在多线程环境中使用智能指针时,尽管std::shared_ptr在某些方面提供了线程安全性,但仍需小心处理对底层对象的访问和修改,通常需要使用互斥锁等同步机制来确保线程安全。而std::unique_ptr则在设计上不支持跨线程的共享,因此需要特别注意所有权的唯一性和转移操作的同步。

免费评分

参与人数 5吾爱币 +10 热心值 +5 收起 理由
asciibase64 + 1 用心讨论,共获提升!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
geesehoward + 1 + 1 我很赞同!
你好,再见 + 1 + 1 用心讨论,共获提升!
道冲渊风 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| licks 发表于 2024-6-28 08:48
ashirogimuto 发表于 2024-6-21 09:31
我其实是想说:对于有好习惯的C++程序猿,普通指针分配内存后,都会注意释放的,所以觉得这个智能的指针没 ...

仁者见仁智者见智吧,可能在某些场合下,会有用处
mastercraker 发表于 2024-7-29 10:02
c/c++玩久了反而觉得这玩意鸡肋,为什么呢,多申请了个对象,多了数个变量和锁判断和控制,只为了避免指针没有释放,这玩意不会影响效率吗?得不偿失,不得不说对于初级程序员来说确实是个利器
你好,再见 发表于 2024-6-20 07:44
ashirogimuto 发表于 2024-6-20 09:54
C++智能指针,看上去这个智能就是能自动内存管理,避免内存泄漏,
也没什么太大的亮点啊。
 楼主| licks 发表于 2024-6-20 10:10
ashirogimuto 发表于 2024-6-20 09:54
C++智能指针,看上去这个智能就是能自动内存管理,避免内存泄漏,
也没什么太大的亮点啊。

我不知道你想要的亮点是什么?类似java语言的那种垃圾回收机制?
ashirogimuto 发表于 2024-6-21 09:31
licks 发表于 2024-6-20 10:10
我不知道你想要的亮点是什么?类似java语言的那种垃圾回收机制?

我其实是想说:对于有好习惯的C++程序猿,普通指针分配内存后,都会注意释放的,所以觉得这个智能的指针没什么用处。
mgm369 发表于 2024-6-21 10:07
谢谢分享
qingchengshuang 发表于 2024-11-12 21:27
学习了,谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-15 20:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表