在c++中,智能指针主要是用来自动管理动态分配(使用new分配)的内存,以帮助避免内存泄漏,悬挂指针等问题。也就是说,无需手动释放这些智能指针管理的堆内存,在智能指针对象过期时,这些内存将自动被释放。
注意:不要将非堆内存用于智能指针
C++标准库(自C++11)提供了如下几种智能指针,位于头文件<memory>中
- std::unique_ptr
- std::shared_ptr
- std::weak_ptr
- std::auto_ptr(在C++17中移除)
意识到下面两点很重要
- 对智能指针对象使用解引用操作符(
*
),这会返回智能指针指向的对象的引用。(也就是相当于对智能指针对象管理的指针使用解引用操作符)。 - 成员访问箭头(
->
)操作符用于访问智能指针指向的对象的成员。(也就是相当于对智能指针对象管理的指针使用成员访问箭头(->
)操作符)。
本文探讨的内容为std::unique_ptr。详细的内容可以参考 cppreference.com
std::unique_ptr初始化
使用new返回的指针初始化一个unique_ptr对象。
初始化一个std::unique_ptr对象的时候必须采用直接初始化,且使用的指针指向堆内存(new分配)。
string* pStr = new string{ "hello unique_ptr." };
std::unique_ptr<string> uniqueStr1(pStr);
//std::unique_ptr<string> uniqueStr1 = pStr; //不支持复制初始化
//所有的智能指针都有一个 explicit的构造函数,构造函数将指针作为参数。因此,不会自动将指针转换为指针指针对象
可以将nullptr赋值给unique_ptr对象
//赋值运算符支持nullptr
uniqueStr1 = nullptr;
//构造函数支持nullptr
unique_ptr<string> uniqueStr2 = nullptr;
std::unique_ptr所有权的转移
1、使用std::move
std::unique_ptr的赋值运算符被重载以接受右值,使得它能够支持移动语义。
string* pStr = new string{ "hello unique_ptr." };
unique_ptr<string> uniqueStr1(pStr);
unique_ptr<string> uniqueStr2 = std::move(uniqueStr1); //uniqueStr1被置为空
2、release成员方法
release成员方法返回一个指向被管理对象的指针,并释放所有权。
string* pStr = new string{ "hello unique_ptr." };
unique_ptr<string> uniqueStr1(pStr);
unique_ptr<string> uniqueStr2(uniqueStr1.release());
3、赋值运算符接收右值unique_ptr对象
可以拷贝或赋值一个临时的右值unique_ptr。
std::unique_ptr<int> clone(int theNum)
{
std::unique_ptr<int> u_p(new int(theNum));
return u_p;
}
int main()
{
std::unique_ptr<int> u_p = clone(10);
}
注意:
默认情况下unique_ptr支持管理动态分配的数组。std::unique_ptr提供了对动态数组的特化版本std::unique_ptr<T[]>,其内部会适当地调用delete[]来释放数组,而非delete。这确保了数组内存被正确释放,避免了潜在的内存泄漏。
std::unique_ptr<int[]> list(new int[5]);
其他成员函数
get()方法返回指向被管理对象的指针
string* str_p = new string{"hello"};
unique_ptr<string> str_up1(str_p);
cout << *str_up1.get() << endl;
//str_up1.get()返回指针str_p
release()方法返回一个指向被管理对象的指针,并释放所有权
string* pStr = new string{ "hello unique_ptr." };
unique_ptr<string> uniqueStr1(pStr);
//uniqueStr1 管理指针pStr string "hello unique_ptr."
unique_ptr<string> uniqueStr2(uniqueStr1.release());
//uniqueStr1 空
//uniqueStr2 管理指针pStr string "hello unique_ptr."
reset()方法替换被管理对象
string* str_p = new string{"hello"};
unique_ptr<string> str_up1 = nullptr;
//str_up1为空
str_up1.reset(str_p);
//str_up1 管理指针str_p string "hello"
swap()方法交换管理对象,和关联的删除器
unique_ptr<string> str_up1(new string{ "hello" });
unique_ptr<string> str_up2(new string{ "world" });
//str_up01 : "hello"
//str_up02 : "world"
str_up1.swap(str_up2);
//str_up01 : "world"
//str_up02 : "hello"
补充
- std::make_unique (c++14)
- 自定义删除器