• 005. C++智能指针


    1. shared_ptr的使用方法
             ① 使用 “make_shared<类型>(初始化指向的对象)“ 生成智能指针
    #include 
    #include 
    #include 
    
    using namespace std;
    
    int main()
    {
        shared_ptr<string>pstring = make_shared<string>("Hello"); // ()内部初始化方式为<类型>的初始化模式
        shared_ptr<string>pstring = make_shared<string>(10, 'p'); // ← 意义同上
        cout<<*pstring;// 使用  * 可以对指针进行解引用
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

                  ②方便起见可以使用auto来进行对智能指针的类型声明

    #include 
    #include 
    #include 
    
    using namespace std;
    
    int main()
    {
        auto pstring = make_shared<string>(10, 'p');
        cout << *pstring;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

                  ③shared_ptr的赋值与引用计数

    #include 
    #include 
    #include 
    
    using namespace std;
    
    int main()
    {
        auto pstring = make_shared<string>(10, 'p');
        auto q = pstring;
        auto r = pstring;
        cout << pstring.use_count(); // use_count()这时的值为3
        {
        	auto q = pstring;
    	    auto r = pstring;
    	    cout << pstring.use_count(); // use_count()这时的值为5
        } // 离开局部作用域会导致,局部作用域内部的智能指针被销毁
        cout << pstring.use_count(); // use_count()这时的值为3
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

                  ④Str_Blob类

    #include
    #include
    #include
    #include
    #include
    
    using namespace std;
    
    class StrBlob
    {
    public:
    	typedef vector<string>::size_type size_type;
    	StrBlob();
    	StrBlob(initializer_list<string> il);
    	size_type size() const
    	{
    		return data->size();
    	}
    	bool empty() const
    	{
    		return data->empty();
    	}
    	// 添加和删除元素
    	void push_back(const string& t)
    	{
    		data->push_back(t);
    	}
    	void pop_back();
    	// 元素访问
    	string& front();
    	string& back();
    	string& front()const;
    	string& back()const;
    private:
    	shared_ptr<vector<string>> data;
    	void check(size_type i, const string& msg) const;
    };
    
    StrBlob::StrBlob() : data(make_shared<vector<string>>())
    {
    
    }
    
    StrBlob::StrBlob(initializer_list<string>li) :data(make_shared<vector<string>>(li))
    {
    
    }
    
    void StrBlob::check(size_type i, const string& msg)const
    {
    	if (i >= data->size())
    	{
    		throw out_of_range(msg);
    	}
    }
    
    string& StrBlob::front()
    {
    	check(0, "front on empty StrBlob");
    	return data->front();
    }
    
    string& StrBlob::back()
    {
    	check(0, "back on empty StrBlob");
    	return data->back();
    }
    
    string& StrBlob::front()const
    {
    	check(0, "front on empty StrBlob");
    	return data->front();
    }
    
    string& StrBlob::back()const
    {
    	check(0, "back on empty StrBlob");
    	return data->back();
    }
    
    void StrBlob::pop_back()
    {
    	check(0, "pop back on empty StrBlob");
    	data->pop_back();
    }
    
    int main()
    {
    	StrBlob b1;
    	{
    		StrBlob b2 = { "a", "an", "the" };
    		b1 = b2;
    		b2.push_back("about");
    		cout << b1.size() << " " << b2.size() << endl;;
    	}
    	cout << b1.size(); // 这里的b1并没有被直接随着b2的销毁而销毁
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

                  ⑤shared_ptr与new结合使用(不可以使用由new创建的指针来隐式转换智能指针)

    #include
    
    using namespace std;
    
    shared_ptr<int> clone(int p)
    {
    	// 这里采用了初始化的方式来使用普通指针初始化智能指针
    	return shared_ptr<int>(new int(p)); // 这里涉及面向返回值类型的隐式转换 |  返回值必须要将普通指针绑定到智能指针上
    }
    
    int main()
    {
    	int p = 100;
    	shared_ptr<int>pointer = clone(p);
    	*pointer += 1;
    	cout << *pointer;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

                  ⑥unique_ptr的初始化与赋值

    #include
    
    using namespace std;
    
    int main()
    {
    	unique_ptr<int>p(new int(42));
    	cout << *p << endl;
    	unique_ptr<int>q;
    	//q = p;//这种行为被禁止,不允许p在释放前赋值
    	//q = p.release(); // 不允许赋值
    	q.reset(p.release()); //将unique_ptr的控制权转让,重置q绑定的内存
    	cout << *q << endl;
    	// cout << *p << endl;	// 会发生堆栈异常 *p已经被释放
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

                  ⑦可以拷贝将亡的unique_ptr以及unique_ptr的局部对象

    #include
    
    using namespace std;
    
    unique_ptr<int> clone_1(int p)
    {
    	return unique_ptr<int>(new int(p)); //拷贝将亡值
    }
    
    unique_ptr<int> clone_2(int p)
    {
    	unique_ptr<int>ret = unique_ptr<int>(new int(p)); //可以拷贝将返回的局部对象
    	return ret;
    }
    
    int main()
    {
    	int p = 10;
    	unique_ptr<int> c1(clone_1(p));
    	unique_ptr<int> c2(clone_2(p));
    	cout << *c1 << "\n" << *c2 << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

                   ⑧ 习题 12.19

    #include
    #include
    #include
    #include
    #include
    #include
    
    using namespace std;
    
    class StrBlobPtr;
    
    class StrBlob
    {
    	friend class StrBlobPtr;
    public:
    	typedef vector<string>::size_type size_type;
    	StrBlob() : data(make_shared<vector<string>>())
    	{
    
    	}
    	StrBlob(initializer_list<string> il):data(make_shared < vector<string>>(il))
    	{
    
    	}
    	size_type size() const
    	{
    		return data->size();
    	}
    	bool empty()const
    	{
    		return data->empty();
    	}
    	// 添加和删除元素
    	void push_back(const string& t)
    	{
    		data->push_back(t);
    	}
    	void pop_back()
    	{
    		check(0, "pop back on empty StrBlob");
    		data->pop_back();
    	}
    	// 元素访问
    	string& front()
    	{
    		// 如果vector为空check会抛出一个异常
    		check(0, "front on empty StrBlob");
    		return data->front();
    	}
    	const string& front()const
    	{
    		check(0, "front on empty StrBlob");
    		return data->front();
    	}
    	string& back()
    	{
    		// 如果vector为空check会抛出一个异常
    		check(0, "back on empty StrBlob");
    		return data->back();
    	}
    	const string& back()const
    	{
    		check(0, "back on empty StrBlob");
    		return data->back();
    	}
    	// 提供给 StrBlobPtr 的接口
    	StrBlobPtr begin();
    	StrBlobPtr end();
    private:
    	shared_ptr<vector<string>>data;
    	void check(size_type i, const string& msg)const
    	{
    		if (i >= data->size())
    		{
    			throw out_of_range("msg");
    		}
    	}
    };
    
    // 当试图访问一个不存在的元素的时候,StrBlob抛出一个异常
    class StrBlobPtr
    {
    	friend bool eq(const StrBlobPtr&, const StrBlobPtr&);
    public:
    	StrBlobPtr() :curr(0)
    	{
    
    	}
    	StrBlobPtr(StrBlob& a, size_t sz = 0) :wptr(a.data), curr(sz)
    	{
    
    	}
    	string& deref()const
    	{
    		auto p = check(curr, "dereference past end");
    		return (*p)[curr]; // 否则,返回指向vector的shared_ptr
    	}
    	StrBlobPtr& incr()	// 前缀递增
    	{
    		check(curr, "increment past the end of StrBlobPtr");
    		++curr;
    		return *this;
    	}
    	StrBlobPtr& decr() // 前缀递减
    	{
    		--curr;
    		check(-1, "decrement past the begin of StrBlobPtr");
    		return *this;
    	}
    private:
    	shared_ptr<vector<string>>check(size_t i, const string& msg) const
    	{
    		auto ret = wptr.lock();
    		if (!ret)
    		{
    			throw runtime_error("unbound StrBlobPtr");
    		}
    		if (i >= ret->size())
    		{
    			throw out_of_range(msg);
    		}
    		return ret; // 否则,返回指向vector的shared_ptr
    	}
    	weak_ptr<vector<string>>wptr;
    	size_t curr;	// 在数组中的当前位置
    };
    
    inline bool eq(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
    {
    	auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
    	// 若底层的vector是同一个
    	if (l == r)
    	{
    		// 则两个指针都指向空,或者指向相同元素的时候,它们相等
    		return (!l || lhs.curr == rhs.curr);
    	}
    	else
    	{
    		return false; // 若指向不同的vector则不可能相等
    	}
    }
    
    inline bool neq(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
    {
    	return !eq(lhs, rhs);
    }
    
    inline StrBlobPtr StrBlob::begin()
    {
    	return StrBlobPtr(*this);
    }
    inline StrBlobPtr StrBlob::end()
    {
    	auto ret = StrBlobPtr(*this, data->size());
    	return ret;
    }
    
    int main()
    {
    	StrBlob b1;
    	{
    		StrBlob b2 = { "a","an","the" };
    		b1 = b2;
    		b2.push_back("about");
    		cout << b2.size() << endl;
    	}
    	cout << b1.size() << endl;
    	cout << b1.front() << " " << b1.back() << endl;
    
    	const StrBlob b3 = b1;
    	cout << b3.front() << " " << b3.back() << endl;
    
    	for (auto it = b1.begin(); neq(it, b1.end()); it.incr())
    	{
    		cout << it.deref() << endl;
    	}
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179

                   ⑨ unique_Ptr自动管理动态数组

    #include
    
    using namespace std;
    
    int main()
    {
    	unique_ptr<int[]>up(new int[10]); // 定义指向10个元素的数组指针
    	up.release(); // 销毁刚刚定义过的指针
    	//为数组中的元素赋值
    	for (int i = 0; i < 10; i++)
    	{
    		up[i] = i;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

                   ⑩ shared_Ptr手动管理动态数组

    #include
    
    using namespace std;
    
    int main()
    {
    	shared_ptr<int[]>sp(new int[10], [](int* p) {delete p; }); // 以lambda表达式的方式定义删除器
    //	sp.reset(); // 使用自定义的删除器来执行智能指针指向数组的释放
    	// 元素访问方式略有差别,shared_ptr不可以使用下标
    	for (int i = 0; i < 10; i++)
    	{
    		*(sp.get() + i) = i;
    	}
    	for (int i = 0; i < 10; i++)
    	{
    		cout << sp[i] << "\t";
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

                   11.allocator使用案例一

    #include
    
    using namespace std;
    
    int main()
    {
    	allocator<string>alloc;
    	auto const p = alloc.allocate(100); // 分配100个未初始化的string对象
    	string s;
    	string* q = p; // q指向第一个string
    	while (cin >> s && q != p + 100)
    	{
    		alloc.construct(q++, s); //用s初始化*q
    	}
    	const size_t size = q - p; // 记住读取了多少个string
    	// 使用数组
    	for (size_t i = 0; i < size; i++)
    	{
    		cout << p[i] << "\t";
    	}
    	while (q != p) // 使用完毕释放已构造的string
    	{
    		alloc.destroy(--q);
    	}
    	alloc.deallocate(p, 100); // 释放内存
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

                   12.allocator使用案例二

    #include
    
    using namespace std;
    
    int main()
    {
    	allocator<int> alloc;
    	auto const p = alloc.allocate(10);
    	int* q = p;
    	int count = 10;
    	while (count--)
    	{
    		int x;
    		cin >> x;
    		*q++ = x;
    	}
    	int size = q - p;
    	for (int i = 0; i < size; i++)
    	{
    		cout << p[i] << " ";
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    华为OD机试 - 智能驾驶 - 广度优先搜索(Java 2024 C卷 200分)
    互联网协议入门详解--五层模型
    Unity 之Material 类型和 MeshRenderer 组件中的 Materials 之间有一些重要的区别
    Redis学习
    生产者消费者模型(linux下c语言实现)
    【Vue3】ref对象类型的响应式数据
    Unity-mask使用
    Express:CORS 跨域资源共享
    docker 安装oracle 19c
    MySQL 练习<3>
  • 原文地址:https://blog.csdn.net/dosdiosas_/article/details/126517950