您的位置:首页 > 编程语言 > C语言/C++

实战c++中的智能指针unique_ptr系列-- unique_ptr的operator=、operator bool、reset、swap、get等介绍

2015-12-25 23:52 567 查看
既然打算把unique_ptr写一个系列,就要详尽一点,有些内容也许在vector的时候有个涉及,但是现在还是再谈论一番。

我们要把unique_ptr看做一个类,废话了,它当然是一个类。所以这个类肯定也重载了赋值运算符,即operator=。现在就开始看看operator=在unique_ptr中的使用:

官方描述如下:

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;


这里简要实例:

#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

唯一需要说明的就是std::move后,foo变为了empty,如果对于这个empty再做一些操作的话,就会导致一些灾难了。

其实说白了,就是摧毁原来的指针,并把新指针指向原来指针指向的对象。。。。

那么接下来reset方法即出厂了,到达上面的效果:

#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


swap

我们在vector里就接触过,unique_ptr同样具有这个成员函数:

Exchanges the contents of the unique_ptr object with those of x, transferring ownership of any managed object between them without destroying either.

最重要的就是没有销毁任何一个:

#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


get

get很简单,唯一需要注意的就是:

Notice that a call to this function does not make unique_ptr release ownership of the pointer (i.e., it is still responsible for deleting the managed data at some point). Therefore, the value returned by this function shall not be used to construct a new managed pointer.

最主要的一点就是,智能指针没有释放,即没有失去所有权:

#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;
}


即上面代码提到的,p = bar.get(); 后,bar并非被释放,也就相当于指针p和智能指针bar共同管理一个对象,所以就*p做的一切,都会反应到bar指向的对象上。

这段代码有了一个与get相对比的方法:release

release

不必多说:

This call does not destroy the managed object, but the unique_ptr object is released from the responsibility of deleting the object. Some other entity must take responsibility for deleting the object at some point.

重点就是一句话:智能指针被释放。

#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;
}


最后了,再介绍一个operator bool吧,即unique_ptr有这样一个成员函数,来检查是否为空:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: