C++备忘录061:smart pointers gist of "Effective Modern C++"
Prefer lambda as custom deleter of std::unique_ptr
#include <memory>
#include <iostream>
struct S {};
auto del1 = [](S *) {};
void del2(S *) {};
int main() {
std::cout << sizeof(std::unique_ptr<S, decltype(del1)>) << '\n'; // 8
std::cout << sizeof(std::unique_ptr<S, void(*)(S*)>) << '\n'; // 16
}
When using the default deleter, you can reasonably assume that std::unique_ptr
objects are the same size as raw pointers.
-
Deleters that are function pointers genenrally cause the size of a
std::unique_ptr
to grow from one word to two. -
For deleters that are function objects, the change in size depends on how much state is stored in the function object.
-
Stateless function objects (e.g., from lambda expressions with no captures) incur no size penalty
Converting a std::unique_ptr
to a std::shared_ptr
is easy
Performance implications of the reference count
-
std::shared_ptr
are twice the size of a raw pointer, because a pointer to the resouce plus a raw pointer to the control block -
Memory for the reference count must be dynamically allocated
-
Increments and decrements of the reference count must be atomic
Specifying a custom deleter doesn’t change the size of a std::shared_ptr
object
std::weak_ptr
objects are the same size as std::shared_ptr
objects, they make use of the same control blocks, and operations such as construction, destruction, and assignment involve atomic reference count manipulations
Prefer std::make_shared
-
Exception safe
-
Allows compilers to generate smaller, faster code.
std::make_shared
requires one memory allocation instead of two
Circumstances that std::make_shared
can’t or shouldn’t be used
-
custom deleter/custom allocator
-
When
std::initializer_list
is used as constructor. Parameters ofmake
functions are considered as paren initialzied. e.g.,std::make_shared<std::vector<int>>(10, 20)
initializes avector
with 10 values set to 20.auto initList = {10, 20}; auto spv = std::make_shared<std::vector<int>>(initList)
-
Control block is placed in the same chunk of memory as the managed object. The managed memory cannot be released until the control block has also been destroyed. As long as
std::weak_ptr
refer to a control block, the memory allocated bymake
, then cannot be deallocated untile the laststd::shared_ptr
and the laststd::weak_ptr
referring to it have been destroyed
上一篇: C++11新特性之八:smart pointers
下一篇: smart pointers