Использование new(this)

355
02 января 2017, 22:58

Читаю C++ Super-FAQ. В разделе Constructors натыкаюсь такое высказывание:

BTW do NOT try to achieve this via placement new. Some people think they can say new(this) Foo(x, int(x)+7) within the body of Foo::Foo(char). However that is bad, bad, bad. Please don’t write me and tell me that it seems to work on your particular version of your particular compiler; it’s bad

Речь идет о том, то что так делать категорически нельзя:

class Foo{
public:
    Foo(char x){
        new (this) Foo(x, int(x)+7); 
    }
    Foo(char x, int y){
        //...
    }
};

Может кто-нибудь более подробно объяснить чем грозит такой трюк?

UPD: Подозреваю что в данном примере все будет нормально, и проблемы начнутся при наследовании, динамическом выделении ресурсов и т.п.

Answer 1

http://ideone.com/gkgi7S:

class Base
{
public:
    Base()  { ptr = new int[100]; cout << "alloc mem at " << ptr << endl; }
    ~Base() { delete [] ptr; cout << "free mem at " << ptr << endl; }
    int * ptr;
};
class Derived: public Base
{
public:
    Derived(int x, int y):x(x),y(y){}
    Derived(int x)
    {
        new(this) Derived(x,0);
    }
    int x, y;
};
int main(int argc, const char * argv[])
{
    Derived d(5);
}

Вывод:

alloc mem at 0070EA58
alloc mem at 0070FFE8
free mem at 0070FFE8

Такого примера достаточно?...

Можно и без наследования - суть не меняется:

class Derived
{
public:
    Derived(int x, int y):x(x),y(y){}
    Derived(int x)
    {
        new(this) Derived(x,0);
    }
    int x, y;
    Base b;
};
Answer 2

Что пишет наместник бога на Земле Страуструп: линк

Пример использования:

/*1*/ char *pBuf  = new char[sizeof(string)]; 
/*2*/ string *p = new (pBuf) string("hi");    
/*3*/ string *q = new string("hi");

В первой строке мы выделяем память, во-второй - мы строим объект на уже выделенном участке памяти. Пример банальный, но суть Вы уловите: мы строим объект на заранее выделенном участке памяти и можем быть уверены в том, что не произойдет отказа в выделении памяти - ведь она уже выделенна в нужном "объеме", если так можно выразится. Реальный пример - какие-то критические секции, для которых важно быстродействие, отсутствие исключений и т.п.

Оператор размещения, например:

const SomeoneClass& SomeoneClass::operator=( const SomeoneClass& other) {
   if ( this != &other ) {
      this->~SomeoneClass();
      new (this) SomeoneClass(other);
   }
   return *this;
}

Ну и обратите внимание что пишет Страуструп оо освобождении памяти в таких случаях.

READ ALSO
Уведомления в трее (WinAPI C++)

Уведомления в трее (WinAPI C++)

Нужно при определённых событиях в программе показывать над её иконкой в трее соответствующие уведомленияКомпилятор MinGW не понимает параметра...

420
Проблема с проходом массива по условию

Проблема с проходом массива по условию

Добрый деньПытаюсь написать простую программу которая будет из исходного текста подставлять другие значения

430
Изучение С++ и что нужно знать дополнительно к данному языку [требует правки]

Изучение С++ и что нужно знать дополнительно к данному языку [требует правки]

Вопрос далеко не новый, но толкового ответа, кроме как рекомендаций литературы я так и не нашелНачал изучать С++, так как после ВУЗа хотелось...

472
Структура БД учета клиентов

Структура БД учета клиентов

Суть следующая, нужно сделать БД учета звонков клиентов и учета заказовМанипулирования с БД будет происходить через PHP

485