26 Aralık 2018 Çarşamba

std::make_unique metodu

std::make_unique
C++14 ile geliyor. std::unique_ptr yaratılmasına yardımcı olur. Bu metod bir şekilde C++11'de gözden kaçmış.

std::make_unique ve array
Açıklaması şöyle.
make_unique distinguishes T from T[] and T[N], unique_ptr(new ...) does not.

You can easily get undefined behaviour (UB) by passing a pointer that was new[]ed to a unique_ptr<T>, or by passing a pointer that was newed to a unique_ptr<T[]>.
Örnek
Array için şöyle tanımlanır.
auto p3 = std::make_unique<char[]>(3);           // C++14
sd::make_unique Biraz Daha Yavaştır
make_unique tüm belleği value initialize eder. İçi şöyledir. new char[size]() kısmına dikkat!
unique_ptr<T>(new typename std::remove_extent<T>::type[size]())
//                                                         ~~~~
Perfect Forwarding
std::make_unique perfect forwarding yapar. Bu kural gereği lvalue bir nesne, referans olarak iletilir. Yani int x tipinde bir lvalue değişken varsa, int& olarak iletilir.

Perfect Forwarding işlemi, std::make_unique veya çağırdığı yardımcı bir metod ile yapılabilir.

make_uniqye  ve constructor parametreleri
Parametreleri std::make_unique() metoduna geçeriz. Şöyle yaparız.
struct position
{
  int x, y;

  position(int x, int y) : x(x), y(y) {}
};

class positioned
{
public:
  positioned(int x, int y) : pos(x, y) {}
private:
  position pos;
};

auto bla = std::make_unique<positioned>(1,2);
make_unique ve exception
Açıklaması şöyle.
C++14 introduced std::make_unique because, as a result of the parameter evaluation order not being specified, this was unsafe:
Elimizde şöyle bir kod olsun
f(std::unique_ptr<MyClass>(new MyClass(param)), g()); // Syntax A
Açıklama şöyle devam ediyor.
Explanation: if the evaluation first allocates the memory for the raw pointer, then calls g() and an exception is thrown before the std::unique_ptr construction, then the memory is leaked.)

Calling std::make_unique was a way to constrain the call order, thus making things safe:
C++14 ile şöyle yaparız
f(std::make_unique<MyClass>(param), g());             // Syntax B

Örnek
Elimizde şöyle bir metod olsun.
process(std::unique_ptr<object>(new object), iMightThrow());
Eğer new object() çağrıldıktan sonra iMightThrow() çağrılır ve exception atarsa memory leak olur.

Şöyle kullanırsak iMightThrow()  exception atsa bile memory leak olmaz.
process(std::make_unique<object>(), iMightThrow());
make_unique metodunu friend yapmak
Burada ilginç bir fikir var. Her platformda çalışacağı garanti değil ancak yine de not almak istedim.
#include <memory>

template <typename T>
class A
{
public:
    //declare make_unique as a friend
    friend std::unique_ptr<A<T>> std::make_unique<A<T&>>();


    static std::unique_ptr<A> CreateA(T x)
    {
        return std::make_unique<A>(x);
    }

protected:
    A(T x) { (void)x; }
};

int main()
{
    std::unique_ptr<A<int>> a = A<int>::CreateA(5);
    (void)a;
    return 0;
}






Hiç yorum yok:

Yorum Gönder