当前位置: 首页 > news >正文

青岛网站建设青岛人员优化方案怎么写

青岛网站建设青岛,人员优化方案怎么写,pageadmin做网站要钱吗,威海网站制作都有哪些文章目录 一、引言二、智能指针的核心原理:RAII三、智能指针的基本使用1. std::unique_ptr2. std::shared_ptr3. std::weak_ptr 三、智能指针的实现原理1. std::unique_ptr 的实现2. std::shared_ptr 的实现3. std::weak_ptr 的实现 四、shared_ptr的线程安全问题1.…

文章目录

  • 一、引言
  • 二、智能指针的核心原理:RAII
  • 三、智能指针的基本使用
    • 1. `std::unique_ptr`
    • 2. `std::shared_ptr`
    • 3. `std::weak_ptr`
  • 三、智能指针的实现原理
    • 1. `std::unique_ptr` 的实现
    • 2. `std::shared_ptr` 的实现
    • 3. `std::weak_ptr` 的实现
  • 四、`shared_ptr`的线程安全问题
    • 1. 引用计数的线程安全
    • 2. 指针本身的线程安全
    • 3. 解决方案

一、引言

在传统 C++ 中,动态内存管理一直是个头疼的问题。程序员需要手动使用 newdelete 来分配和释放内存,稍有不慎就会导致内存泄漏、悬空指针等问题。特别是在异常处理的场景中,资源释放的逻辑很容易被忽略。

C++11 引入的智能指针(Smart Pointer)通过 RAII(Resource Acquisition Is Initialization)技术,彻底改变了这一局面。它让内存管理变得自动化、安全化,大大降低了程序出错的概率。本文将深入探讨 C++11 中三种主要的智能指针:unique_ptrshared_ptrweak_ptr,并通过代码示例展示它们的实现原理。

二、智能指针的核心原理:RAII

RAII 是 C++ 中管理资源的一种重要编程范式,其核心思想是:资源在对象构造时获取,在对象析构时释放。智能指针正是基于这一思想,将动态内存的生命周期与对象的生命周期绑定在一起。

当我们使用智能指针管理内存时,只需要在构造时传入一个原始指针,智能指针会在其生命周期结束时自动释放该内存。即使在异常发生的情况下,栈展开(Stack Unwinding)过程也会确保智能指针的析构函数被调用,从而避免内存泄漏。

三、智能指针的基本使用

1. std::unique_ptr

unique_ptr 是一种独占式智能指针,确保同一时间只有一个智能指针指向该对象。它禁止拷贝,但支持移动语义。

创建与基本操作

#include <memory>
#include <iostream>void unique_ptr_demo() {// 创建 unique_ptrstd::unique_ptr<int> ptr1 = std::make_unique<int>(42);  // C++14 推荐写法std::unique_ptr<int> ptr2(new int(100));  // 传统写法// 使用解引用和箭头操作符std::cout << *ptr1 << std::endl;  // 输出: 42// 移动所有权std::unique_ptr<int> ptr3 = std::move(ptr1);  // ptr1 变为空if (!ptr1) {std::cout << "ptr1 is empty" << std::endl;}// 获取原始指针(谨慎使用)int* raw_ptr = ptr3.get();// 释放所有权int* released = ptr3.release();delete released;  // 需要手动释放// 重置指针ptr2.reset();  // 释放内存,ptr2 变为空
}

管理动态数组:

std::unique_ptr<int[]> arr = std::make_unique<int[]>(5);
for (int i = 0; i < 5; ++i) {arr[i] = i;
}

2. std::shared_ptr

shared_ptr 是一种共享式智能指针,使用引用计数来管理对象的生命周期。多个 shared_ptr 可以指向同一个对象,当最后一个 shared_ptr 被销毁时,对象才会被释放。

创建与引用计数:

void shared_ptr_demo() {// 创建 shared_ptrstd::shared_ptr<int> sp1 = std::make_shared<int>(10);  // 推荐写法std::shared_ptr<int> sp2(new int(20));  // 传统写法// 拷贝构造和赋值std::shared_ptr<int> sp3 = sp1;  // 引用计数+1sp2 = sp1;  // sp2 原来的对象被释放,引用计数+1// 获取引用计数std::cout << "Use count: " << sp1.use_count() << std::endl;  // 输出: 3// 自定义删除器(例如释放文件句柄)std::shared_ptr<FILE> file(fopen("test.txt", "r"), [](FILE* f) {if (f) fclose(f);});
}  // 所有 shared_ptr 离开作用域,对象被释放

3. std::weak_ptr

weak_ptr 是一种弱引用智能指针,不控制对象的生命周期,用于解决 shared_ptr 的循环引用问题。

基本使用:

void weak_ptr_demo() {std::shared_ptr<int> sp = std::make_shared<int>(100);std::weak_ptr<int> wp = sp;  // 不增加引用计数// 检查对象是否存在if (auto locked = wp.lock()) {  // 转换为 shared_ptrstd::cout << *locked << std::endl;  // 对象存在} else {std::cout << "Object expired" << std::endl;}// 查看引用计数std::cout << "Use count: " << wp.use_count() << std::endl;  // 输出: 1
}  // sp 离开作用域,对象被释放

解决循环引用:

class B;class A {
public:std::shared_ptr<B> b_ptr;~A() { std::cout << "A destroyed" << std::endl; }
};class B {
public:std::weak_ptr<A> a_ptr;  // 使用 weak_ptr 避免循环引用~B() { std::cout << "B destroyed" << std::endl; }
};void test_cycle() {std::shared_ptr<A> a = std::make_shared<A>();std::shared_ptr<B> b = std::make_shared<B>();a->b_ptr = b;b->a_ptr = a;  // 不会导致循环引用
}  // a 和 b 都能正确释放

三、智能指针的实现原理

1. std::unique_ptr 的实现

unique_ptr 的核心是禁止拷贝,只允许移动语义,并在析构时释放资源。
所以在实现 unique_ptr 时,必须禁用拷贝构造和拷贝赋值,并显式实现移动构造、移动赋值和资源管理,以确保独占资源的正确性和安全性。

    template<class T>class unique_ptr {public:unique_ptr(T* ptr = nullptr) : _ptr(ptr) {}unique_ptr(unique_ptr&& other) : _ptr(other._ptr) {other._ptr = nullptr;}~unique_ptr() {delete _ptr;}unique_ptr(const unique_ptr&) = delete;unique_ptr& operator=(const unique_ptr&) = delete;unique_ptr& operator=(unique_ptr&& other) {if (this != &other) {delete _ptr;_ptr = other._ptr;other._ptr = nullptr;}return *this;}T& operator*() const {return *_ptr;}T* operator->() const {return _ptr;}T* get() const {return _ptr;}T* release() {T* temp = _ptr;_ptr = nullptr;return temp;}void reset(T* ptr = nullptr) {if (_ptr) {delete _ptr;}_ptr = ptr;}private:T* _ptr;};

2. std::shared_ptr 的实现

shared_ptr 的核心是引用计数。

主要就是当执行拷贝构造、拷贝赋值的时候让计数器++,而当析构的时候让计数器--。如果计数器为 0 就释放掉资源。

    template<class T>class shared_ptr {public:shared_ptr(T* ptr): _ptr(ptr), _pcount(new int(1)){}template<class D>shared_ptr(T* ptr, D del): _ptr(ptr), _pcount(new int(1)), _del(del){}~shared_ptr() {if (--(*_pcount) == 0) {_del(_ptr);delete _pcount;}}shared_ptr(const shared_ptr<T>& sp): _ptr(sp._ptr), _pcount(sp._pcount){(*_pcount)++;}shared_ptr<T>& operator=(const shared_ptr<T>& sp) {if (_ptr != sp._ptr) {if (--(*_pcount) == 0) {_del(_ptr);delete _pcount;}_pcount = sp._pcount;_ptr = sp._ptr;++(*_pcount);}return *this;}T& operator*() {return *_ptr;}T* operator->() {return _ptr;}int use_count() const {return *_pcount;}private:T* _ptr;int* _pcount;std::function<void(T*)> _del = [](T* ptr) { delete ptr; };};

3. std::weak_ptr 的实现

weak_ptr 的核心是弱引用机制,通过独立于 shared_ptr 的引用计数(弱计数)实现对资源的非拥有性访问,主要用于解决循环引用问题

下面的代码现在看不懂没关系,船到桥头自然直。

    template<class T>class weak_ptr {private:T* _ptr;std::atomic<int>* _pcount;std::atomic<int>* _wcount;public:weak_ptr() : _ptr(nullptr), _pcount(nullptr), _wcount(nullptr) {}weak_ptr(const shared_ptr<T>& sp): _ptr(sp._ptr), _pcount(sp._pcount), _wcount(new std::atomic<int>(1)){}weak_ptr(const weak_ptr& wp): _ptr(wp._ptr), _pcount(wp._pcount), _wcount(wp._wcount){if (_wcount) {(*_wcount)++;}}~weak_ptr() {if (_wcount && --(*_wcount) == 0) {if (_pcount && *_pcount == 0) {delete _wcount;}}}weak_ptr& operator=(const shared_ptr<T>& sp) {if (_wcount && --(*_wcount) == 0) {if (_pcount && *_pcount == 0) {delete _wcount;}}_ptr = sp._ptr;_pcount = sp._pcount;_wcount = new std::atomic<int>(1);return *this;}weak_ptr& operator=(const weak_ptr& wp) {if (this != &wp) {if (_wcount && --(*_wcount) == 0) {if (_pcount && *_pcount == 0) {delete _wcount;}}_ptr = wp._ptr;_pcount = wp._pcount;_wcount = wp._wcount;if (_wcount) {(*_wcount)++;}}return *this;}shared_ptr<T> lock() const {if (expired()) {return shared_ptr<T>(nullptr);}return shared_ptr<T>(_ptr);}bool expired() const {return !_pcount || *_pcount == 0;}int use_count() const {return _pcount ? *_pcount : 0;}};

四、shared_ptr的线程安全问题

std::shared_ptr 的线程安全问题需要从 引用计数的原子性指针本身的访问语义 两方面分析。

1. 引用计数的线程安全

shared_ptr 的核心机制是通过 引用计数 管理资源生命周期,其引用计数的操作具有 原子性(由 std::atomic 保证)。具体规则如下:

  1. 原子性操作
    • 引用计数的递增 / 递减(如拷贝构造、赋值、析构)是 原子操作,多线程中无需额外同步。
    • 引用计数的查询(如 use_count())是 非原子操作,可能读取到中间状态(但不会导致程序崩溃,仅可能返回过时值)。
  2. 安全场景
    • 多个线程同时读取 shared_ptr 对象(如调用 use_count()、解引用 *ptr)是安全的,不会导致数据竞争。
    • 一个线程修改 shared_ptr(如赋值、析构),其他线程读取:由于引用计数操作是原子的,不会导致 shared_ptr 对象本身的不一致(但需注意管理对象的线程安全)。

2. 指针本身的线程安全

shared_ptr 管理的 目标对象(*_ptr)的访问 不保证线程安全,需开发者自行处理同步:

  • 数据竞争风险
    如果多个线程通过 shared_ptr 访问同一对象的 可变状态,且未加同步机制,会导致数据竞争:
std::shared_ptr<MyClass> ptr;// 线程 A
ptr->x = 10;  // 危险:未加锁,若线程 B 同时修改 x,发生数据竞争// 线程 B
int val = ptr->x;  // 危险:与线程 A 竞争

3. 解决方案

库里面的 std::shared_ptr 是保证了多个线程同时修改引用计数是原子的,不会导致数据竞争;引用计数的读取操作是安全的,但非原子,可能会读到中间状态。

我们上面实现的 shared_ptr_pcount 的类型是 int*,所以它的引用计数的读取不是线程安全的,可以将它改成 atomic<int>* 类型,用于保证引用计数的线程安全。当然,既然是多线程,那么使用互斥枷锁解决线程安全问题也可以(具体的等后面多线程部分再讲)。

		// 定义的时候:std::atomic<int>* _pcount;// 构造初始化的时候shared_ptr(T* ptr): _ptr(ptr), _pcount(new std::atomic<int>(1)){}
http://www.cadmedia.cn/news/7873.html

相关文章:

  • 电器网站建设策划书seo网站推广方案策划书
  • 邯郸建设企业网站搜索关键词站长工具
  • 重庆专业微网站建设全国疫情实时动态
  • 四平网站建设电话可以进入任何网站的浏览器
  • 政府网站平台日常制度建设百度推广客户端app
  • 食品营销网站建设调查问卷竞价排名
  • 完整php网站开发网站关键词快速排名技术
  • 上海做外贸网站建设绍兴网站快速排名优化
  • 网站建设功能覆盖范围seo网络优化前景怎么样
  • seo网站建设优化什么意思微商软文范例大全100
  • 站长之家统计全自动引流推广软件下载
  • 沈阳微信网站网站开发详细流程
  • 惠州市seo网站设计seo快速培训
  • 前程无忧深圳招聘网站如何做seo整站优化
  • 郑州仿站模板网站建设北京网络营销推广
  • 网站的建设方法有哪些内容seo营销推广
  • 运动服饰网站建设需求分析打开百度搜索
  • 苏州网站开发费用详情百度大搜是什么
  • 网站建设是如何寻找客户的网页制作咨询公司
  • 建设政府信息网站培训课程开发
  • 网站建设公司市场定位游戏推广论坛
  • 网站自助建设平台自建网站平台
  • 陕西营销型网站建设国际网络销售平台有哪些
  • 中国十大货源批发平台浑江区关键词seo排名优化
  • 网页网站制作公司排名前十的大学
  • 合肥网站建设讯息百度搜索引擎下载
  • 西安做网站建设的公司seo页面优化技术
  • 网站怎么做才有效果seo系统教程
  • 网站建设教程突链爱交易平台
  • 网站商城建设多少钱安新seo优化排名网站