欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++备忘录061:smart pointers gist of "Effective Modern C++"

程序员文章站 2022-03-11 17:23:24
...
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.

  1. Deleters that are function pointers genenrally cause the size of a std::unique_ptr to grow from one word to two.

  2. For deleters that are function objects, the change in size depends on how much state is stored in the function object.

  3. 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
  1. 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

  2. Memory for the reference count must be dynamically allocated

  3. 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
  1. Exception safe

  2. 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
  1. custom deleter/custom allocator

  2. When std::initializer_list is used as constructor. Parameters of make functions are considered as paren initialzied. e.g., std::make_shared<std::vector<int>>(10, 20) initializes a vector with 10 values set to 20.

    auto initList = {10, 20};
    auto spv = std::make_shared<std::vector<int>>(initList)
    
  3. 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 by make, then cannot be deallocated untile the last std::shared_ptr and the last std::weak_ptr referring to it have been destroyed

相关标签: C++ c++