此头文件是动态内存管理库的一部分。std::unique_ptr
是一种智能指针,它通过指针持有并管理另一对象,并在 unique_ptr
离开作用域时释放该对象。在发生下列两者之一时,用关联的删除器释放对象:
- 管理它的
unique_ptr
对象被销毁。 - 通过 operator= 或 reset() 赋值另一指针给管理它的
unique_ptr
对象。
成员函数
(构造函数) | 构造新的 unique_ptr (公开成员函数) |
(析构函数) | 析构所管理的对象,如果存在的话 (公开成员函数) |
operator= | 为 unique_ptr 赋值(公开成员函数) |
修改器 | |
release | 返回一个指向被管理对象的指针,并释放所有权 (公开成员函数) |
reset | 替换被管理对象 (公开成员函数) |
swap | 交换被管理对象 (公开成员函数) |
观察器 | |
get | 返回指向被管理对象的指针 (公开成员函数) |
get_deleter | 返回用于析构被管理对象的删除器 (公开成员函数) |
operator bool | 检查是否有关联的被管理对象 (公开成员函数) |
单对象版本, | |
operator*operator-> | 解引用指向被管理对象的指针 (公开成员函数) |
数组版本, | |
operator[] | 提供到被管理数组的有索引访问 (公开成员函数) |
代码示例:
#include <iostream>
#include <memory>
// unique_ptr deleter with state
class state_deleter {
int count_;
public:
state_deleter()
:count_(0) {}
template<class T>
void operator()(T* p) {
std::cout << "[deleted #" << ++count_ << "]\n";
delete p;
}
};
struct C{
int a;
int b;
};
int main()
{
// unique_ptr constructor example
std::default_delete<int> d;
std::unique_ptr<int> u1;
std::unique_ptr<int> u2(nullptr);
std::unique_ptr<int> u3(new int);
std::unique_ptr<int> u4(new int, d);
std::unique_ptr<int> u5(new int, std::default_delete<int>());
std::unique_ptr<int> u6(std::move(u5));
std::unique_ptr<int> u7(std::move(u6));
std::unique_ptr<int> u8(std::auto_ptr<int>(new int));
std::cout << "u1: " << (u1 ? "not null" : "null") << '\n';
std::cout << "u2: " << (u2 ? "not null" : "null") << '\n';
std::cout << "u3: " << (u3 ? "not null" : "null") << '\n';
std::cout << "u4: " << (u4 ? "not null" : "null") << '\n';
std::cout << "u5: " << (u5 ? "not null" : "null") << '\n';
std::cout << "u6: " << (u6 ? "not null" : "null") << '\n';
std::cout << "u7: " << (u7 ? "not null" : "null") << '\n';
std::cout << "u8: " << (u8 ? "not null" : "null") << '\n';
// unique_ptr destructor example
auto deleter = [](int *p) {
delete p;
std::cout << "deleter called\n";
};
std::unique_ptr<int, decltype(deleter)> foo(new int, deleter);
std::cout << "foo " << (foo ? "is not" : "is") << " empty\n";
// unique_ptr::operator= example
std::unique_ptr<int> foo2;
std::unique_ptr<int> bar2{ nullptr };
foo2 = std::unique_ptr<int>(new int(101)); // rvalue
bar2 = std::move(foo2); // using std::move
std::cout << "foo2: ";
if (foo2)
std::cout << *foo2 << '\n';
else
std::cout << "empty\n";
std::cout << "bar2: ";
if (bar2)
std::cout << *bar2 << '\n';
else
std::cout << "empty\n";
// unique_ptr::get vs unique_ptr::release
//foo3 bar3 p3
std::unique_ptr<int> foo3; //null
std::unique_ptr<int> bar3; //null null
int *p3 = nullptr; //null null null
std::cout << "foo3: ";
if(foo3) std::cout << *foo3 << '\n';
else std::cout << "(null)\n";
std::cout << "bar3: ";
if(bar3) std::cout << *bar3 << '\n';
else std::cout << "(null)\n";
std::cout << "p3: ";
if(p3) std::cout << *p3 << '\n';
else std::cout << "(null)\n";
std::cout << '\n';
foo3 = std::unique_ptr<int>(new int(10)); //(10) null null
bar3 = std::move(foo3); //null (10) null
p3 = bar3.get(); //null (10) (10)
*p3 = 20; //null (20) (20)
p3 = nullptr; //null (20) null
std::cout << "foo3: ";
if (foo3) std::cout << *foo3 << '\n';
else std::cout << "(null)\n";
std::cout << "bar3: ";
if (bar3) std::cout << *bar3 << '\n';
else std::cout << "(null)\n";
std::cout << "p3: ";
if (p3) std::cout << *p3 << '\n';
else std::cout << "(null)\n";
std::cout << '\n';
foo3 = std::unique_ptr<int>(new int(30)); //(30) (20) null
p3 = foo3.release(); //null (20) (30)
*p3 = 40; //null (20) (40)
std::cout << "foo3: ";
if (foo3) std::cout << *foo3 << '\n';
else std::cout << "(null)\n";
std::cout << "bar3: ";
if (bar3) std::cout << *bar3 << '\n';
else std::cout << "(null)\n";
std::cout << "p3: ";
if (p3) std::cout << *p3 << '\n';
else std::cout << "(null)\n";
std::cout << '\n';
delete p3;
// unique_ptr::get_deleter example
state_deleter del;
std::unique_ptr<int> p; //使用默认的deleter;
// alpha and beta use independent copies of the deleter:
std::unique_ptr<int, state_deleter> alpha(new int);
std::unique_ptr<int, state_deleter> beta(new int, alpha.get_deleter());
// gamma and delta share the deleter "del" (deleter type is a reference!):
std::unique_ptr<int, state_deleter&> gamma(new int, del);
std::unique_ptr<int, state_deleter&> delta(new int, gamma.get_deleter());
std::cout << "resetting alpha..."; alpha.reset(new int);
std::cout << "resetting beta..."; beta.reset(new int);
std::cout << "resetting gamma..."; gamma.reset(new int);
std::cout << "resetting delta..."; delta.reset(new int);
std::cout << "calling gamma/delta deleter...\n";
gamma.get_deleter() = state_deleter();//新的deleter
// additional deletions when unique_ptr objects reach out of scope (in inverse order of declaration)
// example of unique_ptr::operator bool
std::unique_ptr<int> foo4;
std::unique_ptr<int> bar4(new int(12));
if(foo4) std::cout << "foo4 points to " << *foo4 << '\n';
else std::cout << "foo4 is empty\n";
if(bar4) std::cout << "bar4 points to " << *bar4 << '\n';
else std::cout << "bar4 is empty\n";
// unique_ptr::swap example
std::unique_ptr<int> foo5(new int(10));
std::unique_ptr<int> bar5(new int(20));
std::cout << "foo5:" << *foo5 << '\n';
std::cout << "bar5:" << *bar5 << '\n';
foo5.swap(bar5);
std::cout << "foo5:" << *foo5 << '\n';
std::cout << "bar5:" << *bar5 << '\n';
// unique_ptr::operator*
std::unique_ptr<int> foo6(new int);
std::unique_ptr<int> bar6(new int(100));
std::cout << "foo6: " << *foo6 << '\n';
std::cout << "bar6: " << *bar6 << '\n';
*foo6 = *bar6 * 2;
std::cout << "foo6: " << *foo6 << '\n';
std::cout << "bar6: " << *bar6 << '\n';
// unique_ptr::operator->
std::unique_ptr<C> foo7(new C);
std::unique_ptr<C> bar7;
foo7->a = 10;
foo7->b = 20;
bar7 = std::move(foo7);
if (foo7) std::cout << "foo7: " << foo7->a << ' ' << foo7->b << '\n';
if (bar7) std::cout << "bar7: " << bar7->a << ' ' << bar7->b << '\n';
// unique_ptr::operator[]
std::unique_ptr<int[]> foo8(new int[5]);
for (int i = 0; i < 5; ++i)
foo8[i] = i;
for (int i = 0; i < 5; ++i)
std::cout << foo8[i] << ' ';
std::cout << '\n';
return 0;
}
运行效果:
参考:
https://cplusplus.com/reference/memory/
https://zh.cppreference.com/w/cpp/header/memory