Giriş
Şu satırı dahil ederiz. Placement New "operator new" için overload edilmiş hallerinden birisi
Şu satırı dahil ederiz. Placement New "operator new" için overload edilmiş hallerinden birisi
#include <new>
Wikipedia'daki Placement Syntax bu yazıdaki hemen her şeyi kapsıyor. Ancak ben daha kısa açıklamak istedim.
Heap'ten bellek almak yerine, programcının sağladığı alanı kullanarak nesne yaratılır. Yani mevcut bir belleği kullanarak nesne yaratma anlamına geliyor. Yine null döndüren new kullanımında olduğu gibi new çağrısının içine parametre geçmek gerekiyor. Bu parametre programcının sağladığı bellektir.Söz dizimi şöyle
Foo* foo = new(bellek alanı) Foo();
new (reinterpret_cast<void *>(p)) T(val);
Örnekcast etmeye gerek yok. Şu kod yanlış.
new ((T*)object_) T;
ÖrnekBelleğini kendi içinde taşıyan bir nesne için şöyle yaparız.
template<typename T>
class StaticObject
{
public:
StaticObject() : constructed_(false) {}
~StaticObject()
{
if (constructed_)
((T*)object_)->~T();
}
void construct()
{
assert(!constructed_);
new (object_) T;
constructed_ = true;
}
T& operator*()
{
assert(constructed_);
return *(std::launder((T*)object_)); }
const T& operator*() const
{
assert(constructed_);
return *((T*)object_);
}
private:
bool constructed_;
alignas(alignof(T)) char object_[sizeof(T)];
};
2. AlignmentEğer aynı buffer içine birden fazla nesne yerleştirilecekse alignment'a dikkat etmek gerekir.
Elimizde bir buffer olsun
char *buffer;
Buffer'a ilk yapımızı yerleştirelim. Şöyle yaparız.struct S
{
...
};
S *newS = new(buffer + offset)S;
offset her zaman alignof(S)'nin katı olmalıdır.3. Saçmalık
Sadece saçmalık olsun diye belleği malloc ile ayırıp yine placement new kullanabiliriz.
Örnek
Şöyle yaparız.
auto pBuffer = malloc(sizeof(ClassA));
ClassA *pObject = new (pBuffer) ClassA;
Örnek
Şöyle yaparızint *p = (int*)malloc(sizeof(int));
new (p) int;
*p = 10;
4. DestructorBu şekilde nesne yaratıldıktan sonra delete T yapılamaz! Destructor'ın elle çağrılması gerekir.
Örnek
Şöyle yaparız.
p->~T();Eğer destructor çağrılmaz ise ve bir kaynak yönetilmiyorsa sorun olmaz ancak kodun düzgün olması açısından çağırmak daha iyi.
Örnek
Şöyle yaparız.
void* operator new(std::size_t, void* p) { return p; }
struct X {
X(int);
~X();
};
void f(X* p);
void g() { // rare, specialized use:
char* buf = new char[sizeof(X)];
X* p = new(buf) X(222); // use buf[] and initialize
f(p);
p->X::~X(); // cleanup
}
5. Placement new anti-pattern
Açıklaması şöyle.
Ancak Herb Sutter bu kullanımın tehlikeli olabileceğine dikkat çekmiş. Tehlikeli olabilecek 5 tane madde sıralamış.
Bu kullanım şeklinde assignment operator için copy constructor'daki kodun aynısı yazmak istemeyen tembel programcı aşağıdaki gibi kodluyor. Yani copy constructor re-use edilmiş oluyor.In earlier versions of C++ there was no such thing as placement new; instead, developers used explicit assignment to this within constructors to achieve similar effect. This practice has been deprecated and abolished later, and third edition of The "C++ Programming Language" doesn't mention this technique. Support for placement new operator has been added to compilers circa 1995.
Ancak Herb Sutter bu kullanımın tehlikeli olabileceğine dikkat çekmiş. Tehlikeli olabilecek 5 tane madde sıralamış.
Applepie& Applepie::operator=( const Applepie ©)
{
if( this != ©)
{
this->~Applepie(); // release own object
new(this) Applepie(copy); // placement new copy constructor
}
return *this;
}
Hiç yorum yok:
Yorum Gönder