简介
non-specialized | template <class T, class D = default_delete<T>> class unique_ptr; |
---|---|
array specialization | template <class T, class D> class unique_ptr<T[],D>; |
获取指针的所有权,且该所有权不能共享。
当 unique_ptr 被销毁、或通过赋值操作改变了它的值、或显式调用 unique_ptr:: reset() 函数时,它将会自动销毁指针所指向的内存空间。所以,不能有两个 unique_ptr 同时拥有同一个指针!
#include <iostream>
#include <memory>
int main() {
int* p = new int(4);
std::unique_ptr<int> up1 = std::unique_ptr<int>(p);
// 不行!!
std::unique_ptr<int> up2 = std::unique_ptr<int>(p);
return 0;
}
构造
default (1) | constexpr unique_ptr() noexcept; |
---|---|
from null pointer (2) | constexpr unique_ptr (nullptr_t) noexcept : unique_ptr() {} |
from pointer (3) | explicit unique_ptr (pointer p) noexcept; |
from pointer + lvalue deleter (4) | unique_ptr (pointer p, typename conditional<is_reference<D>::value,D,const D&> del) noexcept; |
from pointer + rvalue deleter (5) | unique_ptr (pointer p, typename remove_reference<D>::type&& del) noexcept; |
move (6) | unique_ptr (unique_ptr&& x) noexcept; |
move-cast (7) | template <class U, class E> unique_ptr (unique_ptr<U,E>&& x) noexcept; |
move from auto_ptr (8) | template <class U> unique_ptr (auto_ptr<U>&& x) noexcept; |
copy (deleted!) (9) | unique_ptr (const unique_ptr&) = delete; |
// unique_ptr constructor example
#include <iostream>
#include <memory>
int main () {
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';
return 0;
}
u1: null
u2: null
u3: not null
u4: not null
u5: null
u6: null
u7: not null
u8: not null
赋值
move assignment (1) | unique_ptr& operator= (unique_ptr&& x) noexcept; |
---|---|
assign null pointer (2) | unique_ptr& operator= (nullptr_t) noexcept; |
type-cast assignment (3) | template <class U, class E> unique_ptr& operator= (unique_ptr<U,E>&& x) noexcept; |
copy assignment (deleted!) (4) | unique_ptr& operator= (const unique_ptr&) = delete; |
// unique_ptr::operator= example
#include <iostream>
#include <memory>
int main () {
std::unique_ptr<int> foo;
std::unique_ptr<int> bar;
foo = std::unique_ptr<int>(new int (101)); // rvalue
bar = std::move(foo); // using std::move
std::cout << "foo: ";
if (foo) std::cout << *foo << '\n'; else std::cout << "empty\n";
std::cout << "bar: ";
if (bar) std::cout << *bar << '\n'; else std::cout << "empty\n";
return 0;
}
foo: empty
bar: 101
重置
void reset (pointer p = pointer()) noexcept;
释放掉现有的所有权,并获取 p 的所有权。
// unique_ptr::reset example
#include <iostream>
#include <memory>
int main () {
std::unique_ptr<int> up; // empty
up.reset (new int); // takes ownership of pointer
*up=5;
std::cout << *up << '\n';
up.reset (new int); // deletes managed object, acquires new pointer
*up=10;
std::cout << *up << '\n';
up.reset(); // deletes managed object
return 0;
}
5
10
释放
pointer release() noexcept;
释放所有权,并置为 nullptr ,返回其管理的指针。此操作并不会销毁指针所指的空间。
// unique_ptr::release example
#include <iostream>
#include <memory>
int main () {
std::unique_ptr<int> auto_pointer (new int);
int * manual_pointer;
*auto_pointer=10;
manual_pointer = auto_pointer.release();
// (auto_pointer is now empty)
std::cout << "manual_pointer points to " << *manual_pointer << '\n';
delete manual_pointer;
return 0;
}
manual_pointer points to 10
解引用
* 运算符 | typename add_lvalue_reference<element_type>::type operator*() const; |
---|---|
-> 运算符 | pointer operator->() const noexcept; |
// unique_ptr::operator*
#include <iostream>
#include <memory>
int main () {
std::unique_ptr<int> foo (new int);
std::unique_ptr<int> bar (new int (100));
*foo = *bar * 2;
std::cout << "foo: " << *foo << '\n';
std::cout << "bar: " << *bar << '\n';
return 0;
}
foo: 200
bar: 100
// unique_ptr::operator->
#include <iostream>
#include <memory>
struct C { int a; int b; };
int main () {
std::unique_ptr<C> foo (new C);
std::unique_ptr<C> bar;
foo->a = 10;
foo->b = 20;
bar = std::move(foo);
if (foo) std::cout << "foo: " << foo->a << ' ' << foo->b << '\n';
if (bar) std::cout << "bar: " << bar->a << ' ' << bar->b << '\n';
return 0;
}
bar: 10 20
访问数组
element_type& operator[](size_t i) const; // only defined in array-specialization
// unique_ptr::operator[]
#include <iostream>
#include <memory>
int main () {
std::unique_ptr<int[]> foo (new int[5]);
for (int i=0; i<5; ++i) foo[i] = i;
for (int i=0; i<5; ++i) std::cout << foo[i] << ' ';
std::cout << '\n';
return 0;
}
0 1 2 3 4
交换
成员函数 | void swap (unique_ptr& x) noexcept; |
---|---|
非成员函数 | template <class T, class D> void swap (unique_ptr<T,D>& x, unique_ptr<T,D>& y) noexcept; |
// unique_ptr::swap example
#include <iostream>
#include <memory>
int main () {
std::unique_ptr<int> foo (new int(10));
std::unique_ptr<int> bar (new int(20));
foo.swap(bar);
std::cout << "foo: " << *foo << '\n';
std::cout << "bar: " << *bar << '\n';
return 0;
}
foo: 20
bar: 10
// unique_ptr swap specialization
#include <iostream>
#include <memory>
int main () {
std::unique_ptr<int> foo (new int(10));
std::unique_ptr<int> bar (new int(20));
swap(foo,bar);
std::cout << "foo: " << *foo << '\n';
std::cout << "bar: " << *bar << '\n';
return 0;
}
foo: 20
bar: 10
其他操作
获取 stored pointer
pointer get() const noexcept;
// unique_ptr::get vs unique_ptr::release
#include <iostream>
#include <memory>
int main () {
// foo bar p
// --- --- ---
std::unique_ptr<int> foo; // null
std::unique_ptr<int> bar; // null null
int* p = nullptr; // null null null
foo = std::unique_ptr<int>(new int(10)); // (10) null null
bar = std::move(foo); // null (10) null
p = bar.get(); // null (10) (10)
*p = 20; // null (20) (20)
p = nullptr; // null (20) null
foo = std::unique_ptr<int>(new int(30)); // (30) (20) null
p = foo.release(); // null (20) (30)
*p = 40; // null (20) (40)
std::cout << "foo: ";
if (foo) std::cout << *foo << '\n'; else std::cout << "(null)\n";
std::cout << "bar: ";
if (bar) std::cout << *bar << '\n'; else std::cout << "(null)\n";
std::cout << "p: ";
if (p) std::cout << *p << '\n'; else std::cout << "(null)\n";
std::cout << '\n';
delete p; // the program is now responsible of deleting the object pointed to by p
// bar deletes its managed object automatically
return 0;
}
foo: (null)
bar: 20
p: 40
获取 stored deleter
deleter_type& get_deleter() noexcept;
const deleter_type& get_deleter() const noexcept;
// unique_ptr deleter with state
#include <iostream>
#include <memory>
class state_deleter { // a deleter class with state
int count_;
public:
state_deleter() : count_(0) {}
template <class T>
void operator()(T* p) {
std::cout << "[deleted #" << ++count_ << "]\n";
delete p;
}
};
int main () {
state_deleter del;
std::unique_ptr<int> p; // uses default 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...";
gamma.get_deleter()(new int);
alpha.get_deleter() = state_deleter(); // a brand new deleter for alpha
// additional deletions when unique_ptr objects reach out of scope
// (in inverse order of declaration)
return 0;
}
resetting alpha...[deleted #1]
resetting beta...[deleted #1]
resetting gamma...[deleter #1]
resetting delta...[deleter #2]
calling gamma/delta deleter...[deleted #3]
[deleted #4]
[deleted #5]
[deleted #2]
[deleter #1]
转换为布尔值
explicit operator bool() const noexcept;
stored pointer 为 null -> false;不为 null -> true 。
// example of unique_ptr::operator bool
#include <iostream>
#include <memory>
int main () {
std::unique_ptr<int> foo;
std::unique_ptr<int> bar (new int(12));
if (foo) std::cout << "foo points to " << *foo << '\n';
else std::cout << "foo is empty\n";
if (bar) std::cout << "bar points to " << *bar << '\n';
else std::cout << "bar is empty\n";
return 0;
}
foo is empty
bar points to 12
关系运算符
支持 == , !=, < , <= , > , >= 。比较的是两者的 stored pointer 。