16 Şubat 2018 Cuma

std::make_shared

Giriş
İmzası şöyle.
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
constructor - Type
Başlığa constructor dedim ancak aslında std::make_shared bir sınıf değil sadece metod. Ancak diğer yazılara benzetmek ve anlamayı kolaylaştırmak için bu şekilde yazdım.

std::make_shared kullanmak, shared_ptr'nin direkt pointer nesnesi ile kurulmasına göre daha verimli.

Sebebi ise, hem nesne için gereken bellek alanının, hem de shared_ptr'nin kendi içinde kullandığı sayaç bellek alanının bir kerede alınması. Yani şu yöntemde gereken tüm bellek bir hamlede alınıyor.
std::shared_ptr<Object> p1 = std::make_shared<Object>("foo");
shared_ptr'nin new'lenen nesne ile kurulmasında ise bellek alanı iki kerede alınıyor. Önce new'lenen nesne için bellek alınır, daha sonra shared_ptr'nin kendi içinde kullandığı bellek alanı alınır.
Yani şu yöntemde bellek iki hamlede alınıyor.
std::shared_ptr<Object> p2(new Object("foo"));
Bu kurala belki bir istisna kodun -fno-rtti seçeneği ile derlenmesi. Bu durumda tek bir new() çağrısı kullanılmıyor. Açıklaması şöyle
Since you've disabled virtual functions the library can't use packed structure (the element, the refcount and the deleter), since that needs type-erasure. so the library needs to allocate the element+ refcount and the deleter separately.
constructor - default 
Yani parametresiz std::make_shared çağrısı. std::make_shared perfect forwarding yapar. Kodu şuna benzer
::new (pv) T(std::forward<Args>(args)...)
Yani kendisine verilen parameteyi nesnenin constructor metoduna geçer. Eğer std::make_shared parametresiz çağrılırsa nesne value initialization'a tabi tutulur. Mesela şöyle çağrılırsa int 0 olarak ilklendirilir.
auto p = std::make_shared<int>();
Benzer bir açıklama da burada.

constructor - const default
default constructor ile aynı. Sadece T parametresi const T olarak kullanılır. Şöyle yaparız.
std::shared_ptr<const Foo> pFoo = std::make_shared<const Foo>();
std::maked_shared ne zaman kullanmaz
Kullanılmayacağı zamanlardan bir tanesi std::shared_ptr'ye custom deleter verileceği zaman.
Effective C++ kitabında kullanılmaması gereken bir madde daha açıklanmış ancak anlamadım.

std:maked_shared ve array
Açıklaması şöyle. Yani std::make_shared ile array kullanmaya C++20 ile başlayabileceğiz.
  • std::shared_ptr supports array types (as of C++17), but std::make_shared does not. This functionality is supported by boost::make_shared
Custom deleter vererek şöyle yapmak zorundayız.
size_t size = ...
auto p =
std::shared_ptr<uint8_t>{new uint8_t[size], std::default_delete<uint8_t[]>()};
Aslında bu durumun standarda girmemesi çok saçma. boost ile bu işi rahatlıkla yapabiliyoruz. Açıklaması şöyle
Side Note: you can use boost::shared_pointer<> with boost::make_shared<T[]>(N), which is being [added to the standard library in c++20.
Şöyle yaparız.
#include "boost/smart_ptr/make_shared_array.hpp"
auto int_arr_ptr = boost::make_shared<int[]>(100);
Şöyle yaparız.
return boost::make_shared<uint8_t[]>(size);

Hiç yorum yok:

Yorum Gönder