| OLD | NEW |
| (Empty) |
| 1 # std::unique_ptr Transition Guide | |
| 2 | |
| 3 Now `std::unique_ptr<T>` is available anywhere in Blink. This document goes thro
ugh various use cases of `OwnPtr<T>` | |
| 4 and how they get converted to `std::unique_ptr<T>` so you can smoothly switch yo
ur mind. | |
| 5 | |
| 6 If you have any uncertainties on using `std::unique_ptr<T>`, ask yutak@chromium.
org (or other C++ gurus around you) | |
| 7 for help. | |
| 8 | |
| 9 ## Creation and Use | |
| 10 | |
| 11 |||---||| | |
| 12 #### OwnPtr | |
| 13 | |
| 14 ```c++ | |
| 15 void f() | |
| 16 { | |
| 17 OwnPtr<T> owned = adoptPtr(new T(argument)); | |
| 18 owned->useThis(); | |
| 19 T& reference = *owned; | |
| 20 T* pointer = owned.get(); | |
| 21 owned.clear(); | |
| 22 owned = adoptPtr(new T); | |
| 23 T* leakedPointer = owned.leakPtr(); | |
| 24 } | |
| 25 ``` | |
| 26 | |
| 27 #### std::unique_ptr | |
| 28 | |
| 29 ```c++ | |
| 30 void f() | |
| 31 { | |
| 32 std::unique_ptr<T> owned(new T(argument)); | |
| 33 // Or: auto owned = WTF::wrapUnique(new T(argument)); †1 | |
| 34 owned->useThis(); | |
| 35 T& reference = *owned; | |
| 36 T* pointer = owned.get(); | |
| 37 owned.reset(); // Or: owned = nullptr | |
| 38 owned.reset(new T); // Or: owned = WTF::wrapUnique(new T) | |
| 39 T* leakedPointer = owned.release(); | |
| 40 } | |
| 41 ``` | |
| 42 |||---||| | |
| 43 | |
| 44 †1 `WTF::wrapUnique()` is particularly useful when you pass a `unique_ptr` to so
mebody else: | |
| 45 | |
| 46 ```c++ | |
| 47 std::unique_ptr<T> g() | |
| 48 { | |
| 49 h(WTF::wrapUnique(new T(argument))); // Pass to a function. | |
| 50 return WTF::wrapUnique(new T(argument)); // Return from a function. | |
| 51 } | |
| 52 | |
| 53 ``` | |
| 54 | |
| 55 You need to `#include "wtf/PtrUtil.h"` for `WTF::wrapUnique()`. | |
| 56 | |
| 57 ## Passing and Receiving | |
| 58 | |
| 59 |||---||| | |
| 60 #### OwnPtr | |
| 61 | |
| 62 ```c++ | |
| 63 void receive(PassOwnPtr<T> object) | |
| 64 { | |
| 65 OwnPtr<T> localObject = object; | |
| 66 } | |
| 67 | |
| 68 void handOver(PassOwnPtr<T> object) | |
| 69 { | |
| 70 receive(object); | |
| 71 } | |
| 72 | |
| 73 void give() | |
| 74 { | |
| 75 OwnPtr<T> object = adoptPtr(new T); | |
| 76 handOver(object.release()); | |
| 77 // |object| becomes null. | |
| 78 } | |
| 79 | |
| 80 void giveDirectly() | |
| 81 { | |
| 82 handOver(adoptPtr(new T)); | |
| 83 } | |
| 84 | |
| 85 PassOwnPtr<T> returning() | |
| 86 { | |
| 87 OwnPtr<T> object = adoptPtr(new T); | |
| 88 return object.release(); | |
| 89 } | |
| 90 | |
| 91 PassOwnPtr<T> returnDirectly() | |
| 92 { | |
| 93 return adoptPtr(new T); | |
| 94 } | |
| 95 ``` | |
| 96 | |
| 97 #### std::unique_ptr | |
| 98 | |
| 99 ```c++ | |
| 100 void receive(std::unique_ptr<T> object) | |
| 101 { | |
| 102 // It is not necessary to take the object locally. †1 | |
| 103 } | |
| 104 | |
| 105 void handOver(std::unique_ptr<T> object) | |
| 106 { | |
| 107 receive(std::move(object)); // †2 | |
| 108 } | |
| 109 | |
| 110 void give() | |
| 111 { | |
| 112 std::unique_ptr<T> object(new T); | |
| 113 handOver(std::move(object)); // †2 | |
| 114 // |object| becomes null. | |
| 115 } | |
| 116 | |
| 117 void giveDirectly() | |
| 118 { | |
| 119 handOver(std::unique_ptr<T>(new T)); // †3 | |
| 120 } | |
| 121 | |
| 122 std::unique_ptr<T> returning() | |
| 123 { | |
| 124 std::unique_ptr<T> object(new T); | |
| 125 return object; // †4 | |
| 126 } | |
| 127 | |
| 128 std::unique_ptr<T> returnDirectly() | |
| 129 { | |
| 130 return std::unique_ptr<T>(new T); // †3, 4 | |
| 131 } | |
| 132 ``` | |
| 133 | |
| 134 |||---||| | |
| 135 | |
| 136 †1 Both `OwnPtr<T>` and `PassOwnPtr<T>` correspond to `std::unique_ptr<T>`, so a
`std::unique_ptr<T>` in the | |
| 137 arugment and a `std::unique_ptr<T>` in the local variable are exactly the same. | |
| 138 | |
| 139 †2 When you release the ownership of an lvalue, you need to surround it with `st
d::move()`. What's an lvalue? If | |
| 140 a value has a name and you can take its address, it's almost certainly an lvalue
. In this example, `object` is | |
| 141 an lvalue. | |
| 142 | |
| 143 †3 You don't have to do anything if you release the ownership of an rvalue. An r
value is a value that is not | |
| 144 an lvalue, such as literals (`"foobar"`) or temporaries (`111 + 222`). | |
| 145 | |
| 146 †4 `return` statements are kind of special in that they don't require `std::move
()` on releasing ownership, even with | |
| 147 an lvalue. This is possible because `return` makes all the local variables go aw
ay by going back to the caller. | |
| 148 | |
| 149 *** aside | |
| 150 *Note:* Well, yes, I know, the definitions of lvalues and rvalues here are not v
ery precise. However, the above | |
| 151 understandings are sufficient in practice. If you want to know further, see | |
| 152 [the wiki about value categories at cppreference.com](http://en.cppreference.com
/w/cpp/language/value_category). | |
| 153 | |
| 154 See also [Dana's guide for rvalue references](https://sites.google.com/a/chromiu
m.org/dev/rvalue-references) | |
| 155 if you want to learn about move semantics. | |
| 156 *** | |
| OLD | NEW |