5 Kasım 2020 Perşembe

operator new - Sınıf İçin (Raw Bellek Alanı)

Giriş
Sınıf için operator new() metodunu override etmek mümkün. Böylece sınıf için custom allocator yazılabilir. Bir kere bile bu işi yapmam gerekmedi. 

Örnek
Sınıf operator  new istenirse şöyle yaparız.
class Foo
{
public:
  void* operator new( size_t );
}
Peki Bu Bize Neden Lazım
Genellikle sınıf için ayrılan bellek alanını takip etmek istersek kullanırız. Elimizde şöyle bir kod olsun
//The `Traceable` struct is used as a base class
//for any object which should be managed by GC.
struct Traceable {
  ObjectHeader *getHeader() { return traceInfo.at(this); }
 
  static void *operator new(size_t size) {
    // Allocate a block:
    void *object = ::operator new(size);
 
    // Create an object header for it:
    auto header = new ObjectHeader{.marked = false, .size = size};
    traceInfo.insert(std::make_pair((Traceable *)object, header));
 
    // Result is the actual block:
    return object;
  }
};
Bu kodda sınıfa bellek alanı ayrılır ve bu bellek alanı bir başka veriyapısı (bu örnekte bir std::map) içinde takip edilir.

Diğer Örnekler
Örnek - Ata Sınıf
Eğer ata sınıf operator new metodunu sunuyorsa kalıtımda da bu operator devreye girer. Örnekte Derived sınıfı Base sınıfın operator new metodunun farklı bir size_t ile çağrılmasına sebep olur.
struct Base
{
  void* operator new (size_t s) { ... }
  int a;
};

struct Derived : public Base
{
  int b;
};

Derived* d = new Derived; 
Örnek
Elimizde şöyle bir kod olsun.
class Test
{
public:
  virtual int testCall() { return 0; };

  static void* operator new(std::size_t);
};

class TestImpl : public Test
{
  virtual int testCall() override
  {
    return i;
  }

  int i = 15;
};

void* Test::operator new(size_t sz)
{
  return ::new TestImpl();
}

void main()
{
  Test * t = new Test(); // Call the new operator, correctly
  int i = test->testCall(); // i == 0 and not 15
}
Açıklaması şöyle.
Note that for every new expression, the two following things will be performed:
1. allocate memory via appropriate operator new.
2. construct the object on the memory allocated by step#1.

So operator new only allocates memory, doesn't construct the object. That means, for Test * t = new Test();, still a Test will be constructed, on the memory allocated by the overloaded operator new; even you constructed a TestImpl inside the operator new, but it'll be overwritten on the same memory soon, after the operator new finished.


Hiç yorum yok:

Yorum Gönder