Страницы

Поиск по вопросам

воскресенье, 8 декабря 2019 г.

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

#cpp


Читаю 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: Подозреваю что в данном примере все будет нормально, и проблемы начнутся при
наследовании, динамическом выделении ресурсов и т.п.
    


Ответы

Ответ 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; };

Ответ 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; } Ну и обратите внимание что пишет Страуструп оо освобождении памяти в таких случаях.

Комментариев нет:

Отправить комментарий