размещение нового VS явного вызова конструктора в C ++ - PullRequest
3 голосов
/ 12 марта 2011

недавно я сталкивался с этими двумя способами создания объекта в определенном месте в памяти:1.

void* mem = malloc(sizeof(T));
T* obj = new(mem) T();

2.

T* obj = (T*)malloc(sizeof(T));
*obj = T();

Второй способ немного короче ... есть другие отличия?С уважением Матеуш

Ответы [ 2 ]

7 голосов
/ 12 марта 2011

Второй путь неправильный, первый правильный.

Вы вызываете оператор присваивания для экземпляра T, связанного с данными мусора.Оператор присваивания ожидает, что экземпляр был правильно инициализирован - например, он может удалить переменные-члены перед присваиванием, что приведет к всевозможным смешным сбоям.См., Например:

struct Foo {
  std::string * Data;
  Foo() : Data(0) {}
  Foo(Foo const & R)  { Data = new std::string(*R.Data); }
  ~Foo() { delete Data; }
  Foo & operator=(Foo const & R) {
    delete Data;
    Data = new std::string(*R.Data);
    return *this;
  }

};

Первый способ обеспечит вызов Foo::Foo(), что приведет к правильной инициализации Data.Второй способ приведет к delete Data;, где Data указывает на какое-то случайное место в памяти.

РЕДАКТИРОВАТЬ:

Вы можете проверить это следующим образом:

void* mem = malloc(sizeof(Foo));
memset(mem, 0xCC, sizeof(Foo)); // malloc doesn't guarantee 0-init
Foo* obj = new(mem) Foo();

А:

Foo * obj = (Foo*)malloc(sizeof(Foo));
memset(obj, 0xCC, sizeof(Foo)); // malloc doesn't guarantee 0-init
*obj = Foo(); // Crash
1 голос
/ 12 марта 2011
*obj = T();

Этот оператор создает объект T в стеке, а затем выполняет присваивание *obj. Это вызвано непредвиденными последствиями.

С другой стороны,

T* obj = new (mem) T();

Этот оператор инициализирует указанный буфер памяти, mem, выполняя метод конструктора T(), как и предполагалось.

...