unique_ptr

举报
无敌清风蓝 发表于 2023/11/22 20:07:19 2023/11/22
【摘要】 同一时刻只能有一个unique_ptr指向这个对象(这块内存),当unique_ptr被销毁时,它所指向的对象也会被销毁 1.形式:unique_ptr<指向的对象类型> 智能指针变量名1.常规初始化 和new配合unique_ptr<int> p2(new int(500)); //直接把它绑定到new返回的指针上2.make_unique函数,C++11里面没有这个函数,但C++14中有...

同一时刻只能有一个unique_ptr指向这个对象(这块内存),当unique_ptr被销毁时,它所指向的对象也会被销毁

1.形式:

unique_ptr<指向的对象类型> 智能指针变量名

1.常规初始化 和new配合

unique_ptr<int> p2(new int(500)); //直接把它绑定到new返回的指针上

2.make_unique函数,C++11里面没有这个函数,但C++14中有

unique_ptr<int> p1 = std::make_unique<int>(100);
auto p2 = std::make_unique<int>(200);
//如果不用make_unique函数,那就只能这样写
shared_ptr<int> p3(new int(100)); //int重复两次,而且不能用auto简写,要不然p3就成裸指针了

2.常用操作

—不支持的操作

unique_ptr<string> ps1(new string("I love China!"));
unique_ptr<string> ps2(ps1); //错误,它不支持复制
unique_ptr<string> ps3 = ps1 //错误,它不支持复制
unique_ptr<string> ps4;
ps4 = ps1;//错误,不支持赋值

—移动语义

虽然它不支持复制,但是它支持移动,通过std::move来把一个unique_ptr转移到其他的unique_ptr

unique_ptr<string> ps1(new string("I love China!"));
unique_ptr<string> ps3 = std::move(ps1); //转移后ps1为空,ps3指向原来ps1所指

—release成员函数

让指针为空,但是内存还在

放弃对指针的控制权啊(切断智能指针和其所指向的对象之间的联系),返回指针(裸指针),将智能指针置空,返回的这个裸指针可以手动delete释放,也可以用来初始化另外一个智能指针,或者给另外一个智能指针赋值

unique_ptr<string> ps1(new string("I love China!"));
unique_ptr<string> ps2(ps1.release());
if(ps1 == nullptr) //条件成立
{
   cout << "ps1被置空" << endl;
}
ps2.relase(); //错误,因为这会导致内存泄露,返回了一个裸指针,但是没有释放
//正确
string * temp = ps2.release(); // 或者auto temp = ps.release();
delete temp;

—reset成员函数

都会释放原来的内存,指针释放不释放不一定

若reset不带参数时,则释放pi指向的对象,把pi置空

若带参数,则释放pi原来指向的内存,让pi指向新内存

//不带参数
unique_ptr<string> prs(new string("I love China!"));
prs.reset(); //不带参数,prs指向的对象释放,prs置空
if(prs == nullptr) //成立
{
    cout << "prs被置空" << endl;
}
//带参数
unique_ptr<string> ps1(new string("I love China1!"));
unique_ptr<string> ps2(new string("I love China2!"));
ps2.reset(ps1.release()); //reset释放ps2原来指向的内存,让ps2指向ps1所指向的内存,同时ps1置空
ps2.reset(new string("I love China1")) //reset参数可以时一个裸指针,reset释放原来ps2指向的内存,让ps2指向新new出来的string

— = nullptr

释放内存,释放指针

— 指向数组

std::unique_ptr<int[]> ptrarray(new int[10]); //前面带上空括号[]表示是数组,下面行才可以用[下标]来引用数组元素

ptrarray[0] = 12;  //数组提供索引运算符[]
ptrarray[1] = 22;
ptrarray[2] = 32; //能访问的下标是0~9,不要超过这个范围

image-20230820074548870

—get成员函数

返回智能指针中保存的对象(裸指针),小心使用,若智能指针释放了所指的对象,则返回的对象也就变得无效了

unique_ptr<string> ps1(new string("I Love China!"));
string * ps = ps1.get();
const char * p1 = ps->c_str();
*ps = "aaa";
const char * p2 = ps->c_str();
//发现p1和p2是不同的内存地址,这是string内部工作机制决定的

``c_str是 C++ 中string类的一个成员函数,它的作用是返回一个指向string对象内部存储的字符串的指针。这个指针指向的是一个以空字符(’\0’)结尾的字符数组,因此我们可以将它传递给一些需要以空字符结尾的字符串作为参数的函数,例如printf` 函数。

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, world!";
    const char* cstr = str.c_str();
    std::cout << cstr << std::endl;
    return 0;
}

在这个例子中,我们定义了一个 string 类型的变量 str,并将其初始化为 "Hello, world!"。然后,我们调用 strc_str 函数来获取一个指向它内部存储的字符串的指针,并将这个指针赋值给了 cstr。最后,我们使用 cout 来输出这个指针所指向的字符串

std::cout << cstr << std::endl; 这行代码输出的结果是 cstr 所指向的内容,即字符串 "Hello, world!"。在 C++ 中,当我们使用 cout 来输出一个 char 类型的指针时,它会自动输出这个指针所指向的以空字符('\0')结尾的字符串。因此,在上面的例子中,cstr 指向的是一个以空字符结尾的字符串,所以当我们使用 cout 来输出 cstr 时,它会自动输出这个字符串。

上面的p1p2 的内存地址不同是因为 string 类型的对象在修改其内容时,可能会重新分配内存来存储新的字符串。当我们修改 string 对象的内容时,它所管理的内存可能会发生变化,因此我们不能保证在修改前后通过调用 c_str 函数获取的指针指向相同的内存地址

为什么有get这个函数呢,因为考虑到有些函数的参数需要的是一个内置指针(裸指针),所以选择 通过get取得这个内置指针并传递给这样的函数,但是注意不要delete这个get到的指针,否则后果很严重

举个例子

#include <iostream>
#include <memory>

void print(int* ptr) {
    std::cout << *ptr << std::endl;
}

int main() {
    std::unique_ptr<int> p(new int(42));
    print(p.get());
    return 0;
}

—*解引用

std::unique_ptr<int[]> ptr(new int[10]);//对于定义的内容是数组,是没有*解引用运算符的
*ptr;//错误

—swap成员函数

交换两个智能指针指向的对象

std::swap(p1, p2);
//或者
p1.swap(p2);

—智能指针名字作为判断条件

unique_ptr<string> ps1(new string("I Love China!"));
//若ps1指向了一个对象,则为true
if(ps1) //成立
{
    cout << "ps1指向了一个对象" << endl;
}

3.尺寸问题

一般情况下,unique_ptr大小和裸指针一样,足够小,足够快,但是如果增加了删除器,则大小可能变,可能不变

string * p;
int i = sizeof(p); //4字节
unique_ptr<string> ps1(new string("I Love China!"));
int j = sizeof(ps1); //4字节

—如果删除器是lambda表达式这种匿名对象,则大小不变

–如果删除器是一个函数,则大小会变

unique_ptr变大肯定对效率有影响,所以把一个函数当作删除器,还是要慎用,这一点和shared_ptr不同,它是不管指定什么删除器,大小都是裸指针的2倍

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。