智能指针unique_ptr用法补充

智能指针unique_ptr一些用法

(1)临时右值赋值

unique_ptr赋值给另一个是,如果unique_ptr是一个临时右值,编译器允许这样做;如果unique_ptr将存在一段时间,编译器禁止这样做。

unique_ptr<My_name>p0;
p0 = unique_ptr<My_name>(new My_name("艾斯卡诺"));

(2)release()释放unique_ptr对指针的控制权,将unique_ptr置为空,返回裸指针。nullptr可以释放unique_ptr控制对象。

(3)std::move可以转移对指针的控制权。(将unique_ptr传递给子函数,在子函数中释放对象)

#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class My_name
{
public:
   string m_name;
   My_name() {cout<<m_name<<"调用构造函数My_name()\n";}
  My_name(const string & name):m_name(name) {cout<<"调用构造函数My_name("<<m_name<<")\n";}
   ~My_name() {cout<<"调用析构函数~My_name("<<m_name<<")\n";}   
}

//函数 module1需要一个指针,但不释放资源
void module1(const My_name* a){
   cout<<a->m_name<<endl;
}
//函数 module2需要一个指针,释放资源
void module2(const My_name* a){
   cout<<a->m_name<<endl;
   delete a;
}
//函数 module3需要一个指针,但不释放资源
void module3(const unique_ptr<My_name>&a){
   cout<<a->m_name<<endl;
}

//函数 module4需要一个指针,释放资源
void module4(unique_ptr<My_name> a){
   cout<<a->m_name<<endl;
}


int main()
{
   My_name* P = new My_name("艾斯卡诺");
 
  cout<<"开始调用函数。\n";
  module1(pu.get());  //把原始指针给module1方法用一下
  module2(pu.release());//把原始指针交给module2函数,失去原始指针控制权后,pu成空指针。
  module3(pu);
  module4(move(pu));//把对原始指针的控制权交给module4的形参
 
   cout<"m_name="<<(*pu1).m_name<<endl;
   cout<"m_name="<<pu1->m_name<<endl;
}



(4)reset()释放对象

void reset(T* _ptr=(T*)nullptr));
pp.reset();//释放pp对象指向的资源对象
pp.reset(nullptr);//释放pp对象指向的资源对象
pp.reset(new AA("bbb");//释放pp对象指向的资源对象

(5)swap()交换两个unique_ptr的控制权

void swap(unique_ptr<T>&Right);

 (6)unique_ptr和普通指针一样,当指向一个类的基类对象时,也具有多态的性质,如同使用裸指针管理基类对象和派生类对象一样。

(7)unique_ptr并不是绝对安全,当用exit()函数退出时,全局的unique_ptr对象可以释放,局部的unique_ptr对象无法释放。

(8)unique_ptr提供了支持数组的具体化版本


#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class My_name
{
public:
   string m_name;
   My_name() {cout<<m_name<<"调用构造函数My_name()\n";}
  My_name(const string & name):m_name(name) {cout<<"调用构造函数My_name("<<m_name<<")\n";}
   ~My_name() {cout<<"调用析构函数~My_name("<<m_name<<")\n";}   
}
int main()
{
   //普通指针数组
   My_name*parr1= new My_name[2];
   //初始化
  // My_name*parr1= new My_name[2]{string("梅利奥达斯"),string("艾斯卡诺"),string("班")};
   parr1[0].m_name = "梅利奥达斯";
   cout<<"parr1[0].m_name="<<parr1[0].m_name<<endl;
   parr1[1].m_name = "艾斯卡诺";
   cout<<"parr1[1].m_name="<<parr1[1].m_name<<endl;


   //智能指针数组
   unique_ptr<My_name[]>parr2(new My_name[2]);
   unique_ptr<My_name[]>parr2(new My_name[2]){string("梅利奥达斯"),string("艾斯卡诺"),string("班")};
   parr2[0].m_name = "梅利奥达斯";
   cout<<"parr2[0].m_name="<<parr1[0].m_name<<endl;
   parr2[1].m_name = "艾斯卡诺";
   cout<<"parr2[1].m_name="<<parr1[1].m_name<<endl;   

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
智能指针 智能指针shared_ptr的⽤法 的⽤法   为了解决C++内存泄漏的问题,C++11引⼊了智能指针(Smart Pointer)。   智能指针的原理是,接受⼀个申请好的内存地址,构造⼀个保存在栈上的智能指针对象,当程序退出栈的作⽤域范围后,由于栈上的变 量⾃动被销毁,智能指针内部保存的内存也就被释放掉了(除⾮将智能指针保存起来)。   C++11提供了三种智能指针:std::shared_ptr, std::unique_ptr, std::weak_ptr,使⽤时需添加头⽂件<memory>。   shared_ptr使⽤引⽤计数,每⼀个shared_ptr的拷贝都指向相同的内存。每使⽤他⼀次,内部的引⽤计数加1,每析构⼀次,内部的引⽤ 计数减1,减为0时,删除所指向的堆内存。shared_ptr内部的引⽤计数是安全的,但是对象的读取需要加锁。 1. shared_ptr的基本⽤法 初始化   可以通过构造函数、std::make_shared<T>辅助函数和reset⽅法来初始化shared_ptr: #include "stdafx.h" #include <iostream> #include <future> #include <thread> using namespace std; class Person { public: Person(int v) { value = v; std::cout << "Cons" <<value<< std::endl; } ~Person() { std::cout << "Des" <<value<< std::endl; } int value; }; int main() { std::shared_ptr<Person> p1(new Person(1));// Person(1)的引⽤计数为1 std::shared_ptr<Person> p2 = std::make_shared<Person>(2); p1.reset(new Person(3));// ⾸先⽣成新对象,然后引⽤计数减1,引⽤计数为0,故析构Person(1) // 最后将新对象的指针交给智能指针 std::shared_ptr<Person> p3 = p1;//现在p1和p3同时指向Person(3),Person(3)的引⽤计数为2 p1.reset();//Person(3)的引⽤计数为1 p3.reset();//Person(3)的引⽤计数为0,析构Person(3) return 0; }   注意,不能将⼀个原始指针直接赋值给⼀个智能指针,如下所⽰,原因是⼀个是类,⼀个是指针。 std::shared_ptr<int> p4 = new int(1);// error   reset()包含两个操作。当智能指针中有值的时候,调⽤reset()会使引⽤计数减1.当调⽤reset(new xxx())重新赋值时,智能指针⾸先是⽣ 成新对象,然后将就对象的引⽤计数减1(当然,如果发现引⽤计数为0时,则析构旧对象),然后将新对象的指针交给智能指针保管。 获取原始指针   std::shared_ptr<int> p4(new int(5)); int *pInt = p4.get(); 指定删除器   智能指针可以指定删除器,当智能指针的引⽤计数为0时,⾃动调⽤指定的删除器来释放内存。std::shared_ptr可以指定删除器的⼀个原 因是其默认删除器不⽀持数组对象,这⼀点需要注意。   2. 使⽤shared_ptr需要注意的问题   但凡⼀些⾼级的⽤法,使⽤时都有不少陷阱。 不要⽤⼀个原始指针初始化多个shared_ptr,原因在于,会造成⼆次销毁,如下所⽰: int *p5 = new int; std::shared_ptr<int> p6(p5); std::shared_ptr<int> p7(p5);// logic error 不要在函数实参中创建shared_ptr。因为C++的函数参数的计算顺序在不同的编译器下是不同的。正确的做法是先创建好,然后再传 ⼊。 function(shared_ptr<int>(new int), g()); 禁⽌通过shared_from_this()返回this指针,这样做可能也会造成⼆次析构。 避免循环引⽤。智能指针最⼤的⼀个陷阱是循环引⽤,循环引⽤会导致内存泄漏。解决⽅法是AStruct或BStruct改为weak_ptr。 struct AStruct; struct BStruct; struct AStruct { std::shared_ptr<BStruct> bPtr; ~AStruct() {
unique_ptr 是 C++11 中引入的智能指针,用于管理动态分配的对象。 unique_ptr 的特性是:它是唯一拥有(unique ownership)被管理对象的智能指针,也就是说,同一时间只能有一个 unique_ptr 指向一个对象。当 unique_ptr 被销毁时,它会自动释放所管理的对象内存。 下面是 unique_ptr 的简单实现: ```cpp template <typename T> class unique_ptr { public: unique_ptr(T* ptr = nullptr) : m_ptr(ptr) {} ~unique_ptr() { delete m_ptr; } unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; unique_ptr(unique_ptr&& other) noexcept : m_ptr(other.m_ptr) { other.m_ptr = nullptr; } unique_ptr& operator=(unique_ptr&& other) noexcept { if (this != &other) { delete m_ptr; m_ptr = other.m_ptr; other.m_ptr = nullptr; } return *this; } T* get() const { return m_ptr; } T* operator->() const { return m_ptr; } T& operator*() const { return *m_ptr; } private: T* m_ptr; }; ``` 这是一个简化版本的 unique_ptr,它包含了基本的功能,如构造函数、析构函数、移动构造函数、移动赋值运算符,以及 get()、operator->() 和 operator*() 方法。 需要注意的是,这个实现并不完整,只是为了演示 unique_ptr 的基本原理和用法。实际使用时,应该考虑更多的细节,如空指针检查、自定义删除器等。另外,C++11 中已经提供了标准库中的 unique_ptr 实现,我们通常会使用标准库中的智能指针而不是自己实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖爱Kun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值