LINUX.ORG.RU

Реинициализировать объект C++ в стеке

 , , ,


0

2

Допустим, есть объект (наследник QObject), созданный в стеке.

MyClass obj (param);

В определённый момент нужно на том же месте заново создать объект того же класса (аналогично delete и new, если бы он был в куче).

В общем случае должно прокатывать следующее:

obj = MyClass(param);

Но Qt не допускает использования оператора присваивания для qobject-ов: http://doc.qt.io/qt-5/qobject.html#Q_DISABLE_COPY

Соответственно, при сборке вылетает ошибка use of deleted function.

Можно ли как обойти эту проблему? Или только переписывать с использованием кучи?

struct test {
    test( std::string tt )
    { t = tt; }
    std::string t;
};
...
    test tt("1");
    tt.~test( );
    new (&tt) test("2");

а лучче swap реализовать, да.

anonymous
()

ну так и создавай объект. пока что ты вместо этого создал ещё один объект, вызвал конструктор копирования и деструктор вновь созданного объекта. оно тебе надо? в чём вообще состоит идея «создания объекта на том же месте»? что ты под этим подразумеваешь?

Iron_Bug ★★★★★
()
Ответ на: комментарий от anonymous

И не понимаю, что тут такого. Если бы объект был в куче, не было бы ничего странного. Мне чисто для интереса интересно, можно ли такое сделать, не прибегая к куче, на которую все жалуются, когда ругают C++.

te111011010
() автор топика
Ответ на: комментарий от te111011010

В общем если тебе понадобилось такое, то в консерватории явно что-то не так.

Давай свой случай, и показывай почему именно нужно именно имя и именно тоже самое.

anonymous
()
Ответ на: комментарий от te111011010

ну вон в первом ответе есть. Только способ корявый. Если конструктор исключение выбросит, то получишь просто кусок памяти с непонятно чем. Лучше swap завести.

anonymous
()
Ответ на: комментарий от anonymous

Если конструктор исключение выбросит, то получишь просто кусок памяти с непонятно чем.

И чем это грозит? Конструктор не отработал - значит деструктор вызываться не будет, тут всё ок. Память со стека тоже почистится. Можно, конечно, сам placement new в try/catch завернуть, но зачем так делать?

DarkEld3r ★★★★★
()

Ты хочешь переиспользовать туже память или просто обращаться по одному и тому же названию?

Если второе, то можешь завести указатель на этот объект и обращаться к нему.

Если первое, то только каким-нибудь memcpy() память скопировать, но так делать, скорее всего, нельзя. Ибо в деструкторе QObject удаляет указатели на себя, соответственно, для первого экземпляра нельзя вызывать деструктор. А уж что там в сигнал-слотах творится я не знаю. В общем в некоторых условиях можно извернуться, но кому это надо непонятно.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от DarkEld3r

это тем грозит, что по стандарту это UB для нетривиальных конструкторов-деструкторов. а в случае ТСа объект культи точно имеет нетривиальные конструкторы и деструкторы.

Iron_Bug ★★★★★
()
Ответ на: комментарий от te111011010

кучу ругают либо аристократы, либо дегенераты.

до первого тебе пока далеко. и скорость выделения ресурсов в куче, учитывая то, что вся Qt целиком сделана на указателях и динамике, - это самое меньшее, что тебя должно волновать. остальные же претензии к куче происходят от непонимания принципов работы с памятью и исходят от денегератов. в контексте работы с Qt избегать работы с кучей по меньшей мере нелогично.

Iron_Bug ★★★★★
()
Ответ на: комментарий от anonymous

Кажется, заработало, спасибо. Но нужно ли в данном случае вызывать delete?

Хотя скорее всего перепишу на кучу.

te111011010
() автор топика
Ответ на: комментарий от Iron_Bug

это тем грозит, что по стандарту это UB для нетривиальных конструкторов-деструкторов.

Можно подробнее где именно и откуда возьмётся UB?

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

дядя, ты дурак? в конце блока вызовется десруктор для десрукторнотого объекта. дабл деструкт, что очень весело как бы, да.

anonymous
()

obj = MyClass(param);

В общем случае оно как раз не прокатит, ибо operator= может быть перегружен и делать ничего.

Пересоздание объекта на стеке вообще делается через ручной вызов деструктора и placement_new по адресу объекта. Если это надо, конечно

yoghurt ★★★★★
()
Последнее исправление: yoghurt (всего исправлений: 1)
Ответ на: комментарий от DarkEld3r

Конструктор не отработал - значит деструктор вызываться не будет, тут всё ок. Память со стека тоже почистится.

Аффтар, пеши исчо !

utf8nowhere ★★★
()
Ответ на: комментарий от te111011010

Но нужно ли в данном случае вызывать delete?

Разве что для стека. Не нужно, в общем.

evilface ★★
()
Ответ на: комментарий от DarkEld3r

оттуда, что ты не знаешь, что происходит в культе и она может внезапно дёрнуть какой-нибудь сигнал-слот, в котором была - внезапно! - ссылка на тот самый объект, который ты уничтожил.

noncopyable от нефиг делать не делают. и если авторы сделали объект таким, значит, во-первых, там кастомные конструкторы-деструкторы и, во-вторых, не надо выпендриваться, а нужно использовать стандартные методы работы с такими объектами. а все ваши извращения с UB могут не выстрелить при тестировании, но вылезут где-то позже. и будет весело. вы тут дурные идеи нубам подбрасываете, а потом вся эта пионерия с кривыми велосипедами лезет сюда с вопросами «ой, а почему у меня непонятно где программа падает?!».

Iron_Bug ★★★★★
()
Ответ на: комментарий от anonymous

в конце блока вызовется десруктор для десрукторнотого объекта.

Да, ты прав, это я туплю.

DarkEld3r ★★★★★
()
Ответ на: комментарий от utf8nowhere

Аффтар, пеши исчо !

Ну протупил, с кем не бывает. В «обычных условиях» всё-таки это правило выполняется.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Конструктор не отработал - значит деструктор вызываться не будет, тут всё ок.

Нет. Это ничего не значит кроме как «в объекте сейчас непонятно что, так как конструктор выкинул исключение».

Aswed ★★★★★
()

Кароч. И используй каноничный вариант с кучей

MyClass* obj = new MyClass(param);
....
delete obj;
obj = new MyClass(param1);
Либо сделай какой-нибудь метод ему, что б свойства поменять и перевести его в новое состояние, если память тратить не хочешь.

Aswed ★★★★★
()
Ответ на: комментарий от Iron_Bug

Если он вручную вызовет деструктор перед вызовом конструктора, то разве объект не должен будет все указали на себя убрать отовсюду? Ибо если delete объекта в куче безопасен, значит объект таки умеет подчищать за собой в деструкторе.

KivApple ★★★★★
()

Тупнякотред

anonymous
()
Ответ на: комментарий от KivApple

в культе обычно родители удаляют детей. и дочерний объект вообще может не знать о том, какие на него есть ссылки.

Iron_Bug ★★★★★
()
Ответ на: комментарий от te111011010

Чтобы имя переменной было одно и то же.

В функциональных ЯП, в который проповедуется тотальная константность, была придумана возможность получить то же имя переменной с другим значением не нарушая принцип иммутабельности. В переводе на плюсы, это будет выглядеть так

MyClass obj(param1);
{
  MyClass obj(param2);
  ...
}

И пусть оно работает только в рамках одной функции, всеравно стековые переменные и живут в рамках одной функции. Если же ТС решит передать ссылку на стековую переменную в другую функцию и переинициализировать ее там, то это уже не лечится.

q0tw4 ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.