25 Aralık 2018 Salı

std::unique_ptr ve Custom Deleter

Giriş
Scott Meyer’in “Effective Modern C++” kitabındaki açıklama şöyle.
Deleters that are function pointers generally 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, and this means that when a custom deleter can be implemented as either a function or a captureless lambda expression, the lambda is preferable.
custom deleter metodu olarak lambda
custom deleter lambda olarak tanımlanabilir.
Örnek
Stack'te yaratılan bir değişkeni silmemek için hiçbir şey yapmayan bir custom deleter şöyle tanımlanır.
auto noop = [](int*){};
std::unique_ptr<int, decltype(noop)>intptr(&a, noop);
loglama yapan bir custom deleter şöyle tanımlanır.
auto deleter_ = [](int *p) { doSth(p); delete p; };
std::unique_ptr<int, decltype(deleter_)> up(new int, deleter_);
Örnek
Şöyle yaparız.
void foo(bool & currState, bool newState)
{
  bool prevState = currState;
  currState      = newState;
  std::unique_ptr<bool, std::function<void(bool*)>> txEnder(&prevState,
    [&prevState, &currState](bool* p) {
      currState = prevState;
  });
  cout << "currState: " << currState << endl;
}
custom deleter metodu olarak functor
Örnek
map<int,int*> olarak düşünürsek int* yerine unique_pte gelirse şöyle yaparız.
struct Deleter {
  void operator()(int* i) { delete i; }
};

std::map<int, std::unique_ptr<int, Deleter>> m;

void foo(int* i) {
    m[0] = std::unique_ptr<int, Deleter>(i);
}
Örnek
Stack'te yaratılan bir değişkeni silmemek için hiçbir şey yapmayan bir custom deleter şöyle tanımlanır.
struct D{

  void operator()(int* p) const {
    std::cout << "Deleter \n";
    //... no actual delete
  }
};  

int a =5;    
std::unique_ptr<int,D> intptr (&a);
custom deleter olarak free
Şöyle yaparız.
struct free_deleter {
  template <typename T> void operator()(T* p) const {
    ::free(p);
  }
};
template <typename T> using malloc_ptr = std::unique_ptr<T, free_deleter>;
Şöyle yaparız.


malloc_ptr<char> ptr (static_cast<char*>(::malloc(100)));

1 yorum:

  1. Blog sitenizi çok hoş buldum yeni keşfettim ayrıca attığınız her adımda başarılı olmanız ümidiyle..

    Bende sizi kişisel blogger siteme beklerim ZanaLab
    https://www.zanalab.com ya da www.zanalab.com

    YanıtlaSil