LINUX.ORG.RU

Деструкторы не нужны (?)

 


0

5

Тут в соседней теме один анон сказанул следующее:

Дело не в том. Сишка, она про написание руками + можно навесит абстракций, аки глиб/гобджект. Кресты же — изначально нагромождение абстракций со строками, срущими в кучу, функциональными объектами, методами, вызывающимися неявно (например, деструкторы, на которые жаловался кармак) и проч

Собственно, хотелось бы поговорить о выделенном.

Антон прикрылся ссылкой, по которой про деструкторы я так ничего и не нашёл. Более того, в твиттере Кармака всё выглядит с точностью до наоборот — https://twitter.com/id_aa_carmack/status/172340532419375104

RAII constructor / destructor pairing and templates for type safe collections are pretty high on my list of C++ benefits over C

Кто прав? Кто виноват? И нужны ли в итоге C++ деструкторы?

Ответ на: комментарий от monk

С++ с отлавливаемыми исключениями в деструкторе уже другой. По определению.

Это только мне кажется, что в этой точке разговоры про деструкторы C++ уже теряют смысл. Ибо начинаются фантазии на тему, какой бы C++ хотел бы использовать monk. С вполне естественным вопросом: почему же он не использует то, что ему хочется использовать?

Если обязательно обрабатываются до вызова, то тогда их ловить можно только внутри деструктора invalid_user.

Так я и спрашиваю, как это выразить в синтаксисе языка.

По поводу вот этого:

a();
try {
try { ... }
catch( const invalid_user & x ) {...}
} catch (...) { обработать ошибку invalid_user }
b();
даже комментировать не хочется. Т.к. явно кто-то из нас тупит.

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

С++ с отлавливаемыми исключениями в деструкторе уже другой. По определению. Ладно, для совместимости пусть будет:

catch (exception &e) { /* поймали exception */ }
catchmany (exception *e) { /* поймали много exception */ }

Это какой-то C головного мозга, с C++ так даже в 90-х не стали бы делать.

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

Тут почти то же самое: совместимость.

А вы, оказывается, не способны прочитать дальше первого ответа.

Хотя она и так сломана, так как в нынешнем C++ ещё работает:

Кто вам сказал, что в C++ нельзя выпускать исключения из деструкторов? Можно и даже есть, как минимум, одна библиотека, которая это делает.

Вот исключение из деструктора, которое вылетело, когда идет раскрутка стека из-за предыдущего исключения — вот это уже сразу std::terminate.

Поэтому, собственно, и не принято в C++ бросать исключения в деструкторе.

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

Ну пусть эксперт напишет свой Qt с объектами и исключениями.

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

Опять же, никто не заставляет пользоваться Qt. Не нравится - не ешь.

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

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

Мне казалось, ему уже хуже не будет. PL/1 двадцать первого века уже получился.

А все потому, что люди, привыкшие к более безопасным средам, не могут привыкнуть к тому, что и как делается в C++

В общем да. Если язык для маленьких утилит и системного программирования (как C), то можно понять и принять и UB на невинно выглядящие операции и отсутствие реального контроля за памятью (кода немного, RTTI на микроконтроллерах дорог). Но когда уже была разработана Ада, делать из С++ монстра, из которого со всех сторон текут абстракции, по-моему было неосмотрительно.

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

Кто вам сказал, что в C++ нельзя выпускать исключения из деструкторов? Можно и даже есть, как минимум, одна библиотека, которая это делает.

А как это согласуется с тем, что теперь деструкторы noexcept? Насколько я помню, если из функции, помеченной noexcept выходит исключение, то программа аварийно завершается.

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

Это только мне кажется, что в этой точке разговоры про деструкторы C++ уже теряют смысл. Ибо начинаются фантазии на тему, какой бы C++ хотел бы использовать monk.

Можешь придумать другой синтаксис с нормальными (взаимодействующими с исключениями) деструкторами. Я всего лишь показываю, что если бы у разработчиков было желание, то сделать они это могли бы.

почему же он не использует то, что ему хочется использовать?

Использую. Racket, Haskell, Common Lisp.

Так я и спрашиваю, как это выразить в синтаксисе языка.

invalid_user::~invalid_user()
{
  try {
    
  } catch (...) {
    обрабатываем все нештатные ситуации при уничтожении invalid_user,
в том числе исключения деструкторов полей
  }
}

даже комментировать не хочется. Т.к. явно кто-то из нас тупит.

А что не так-то? Ошибка будет обработана? Будет. b() будет вызвана? Будет.

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

Кто вам сказал, что в C++ нельзя выпускать исключения из деструкторов?

$ cat test.cpp
#include <iostream>

class A
{
public:
  ~A() { throw 1; };
};

int main()
{
  try {
  A a;
  } catch (...) { std::cout << "ok\n"; }
}
$ g++ test.cpp
$ ./a.out
ok
$ g++ -std=c++11 test.cpp
$ ./a.out
terminate called after throwing an instance of 'int'
Аварийный останов
monk ★★★★★
()
Ответ на: комментарий от monk

А как это согласуется с тем, что теперь деструкторы noexcept?

Это они по дефолту noexcept. Но перестают таковыми быть, например, если явно помечены как noexcept(false). Или если так помечен деструктор у базового класса. Можете попробовать на g++ 6.1 с ключиком -std=c++11 и -Wall:

#include <iostream>

class A0
{
public:
  virtual ~A0() noexcept(false) {} 
};

class A : public A0
{
public:
  ~A() { throw 1; };
};

int main()
{
  try {
  A a;
  } catch (...) { std::cout << "ok\n"; }
}
Если у базового класса убрать noexcept(false) то и компилятор выдаст предупреждение, и std::terminate будет вызван.

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

Это они по дефолту noexcept.

Так я про то же. Аргумент «теперь весь старый код будет работать не так» применим и здесь. Могли бы сразу и запретить из noexcept кода вызывать код noexcept(false). Хуже бы не стало.

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

Но когда уже была разработана Ада, делать из С++ монстра, из которого со всех сторон текут абстракции, по-моему было неосмотрительно.

Так кто вас заставляет пользоваться C++? Есть та самая Ada, пишите на ней, какие проблемы.

Ну а если потребовалось воспользоваться C++, то можно сколько угодно исходить на говно на LOR-е, но C++ от этого не изменится.

Можешь придумать другой синтаксис с нормальными (взаимодействующими с исключениями) деструкторами.

Мне-то это не нужно. Это вы хотите иметь другой C++, только как он будет выглядеть вы не можете придумать.

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

Хреново у вас получается.

А что не так-то? Ошибка будет обработана? Будет. b() будет вызвана? Будет.

Продолжаем тупить? Ну смотрите:

a();
try {
  ...;
  if(something) throw invalid_sequence();
  ...
  if(something_else) throw invalid_user();
}
catch(const invalid_user & x) {...}
b();
Если в деструкторе invalid_user выскакивает invalid_sequence, то ваш код не сможет отличить invalid_sequence, который вылетел в основном try, от invalid_sequence, который вылетел в деструкторе invalid_user.

Как-то все улучшатели C++ начинают непадецки тупить на демонстрации того, чего же они хотят от C++.

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

Аргумент «теперь весь старый код будет работать не так» применим и здесь. Могли бы сразу и запретить из noexcept кода вызывать код noexcept(false). Хуже бы не стало.

Это ваше личное мнение. Подтвердить которое кроме как «мамой клянусь» вы вряд ли сможете.

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

Если в деструкторе invalid_user выскакивает invalid_sequence, то ваш код не сможет отличить invalid_sequence, который вылетел в основном try, от invalid_sequence, который вылетел в деструкторе invalid_user.

В любом catch невозможно отличить вызов throw из одного места, от вызова throw с таким же параметром из другого.

Чем это принципиально отличается от

try {
  ...;
  if(something) throw invalid_user();
  ...
  if(something_else) throw invalid_user();
}
catch(const invalid_user & x) {...}
который не сможет отличить invalid_user, который вылетел в something, от invalid_user, который вылетел в something_else?

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

Это ваше личное мнение.

«Хуже бы не стало» — это личное мнение. Всё остальное я фактами подтвердил.

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

И всё это используешь в работе?

Если «в работе», то ещё 1С добавить надо. Контекст был про «хочется использовать и использую».

Интересная у вас кодовая база.

Так я не (командный) программист. Я сисадмин. Поэтому 90% программ пишу для себя и пользователей, которых вижу вживую. И если программа требуется в виде бинарника, то пишу на чём удобнее.

Ограничалка трафика (web-морда к tc и MS AD) на Racket, чат на Racket, выдиралка данных с сайта на Racket, генератор tex-документов на Haskell (предыдущая версия на CL), парсер на CL. Ну и скрипты по мелочи.

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

Интересная у вас кодовая база.

Так я не (командный) программист.

Это многое говорит о размерах программ, которые ты пишешь.

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

И программы твои живут... неделю? Месяц?

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

Это многое говорит о размерах программ, которые ты пишешь.

Да. Максимум около 12К строк.

И программы твои живут... неделю? Месяц?

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

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

В любом catch невозможно отличить вызов throw из одного места, от вызова throw с таким же параметром из другого.

Ахринеть, дайте два!

try { // block 1.
  ...
}
catch(const invalid_user &) {...} // For block 1 only.
try { // block 2.
  ...
}
catch(const invalid_user &) {...} // For block 2 only.
На уровне языка прекоасно все разруливается. От вас же я просил показать, как ловить исключения, вылетевшие из конкретного блока catch. Но безрезультатно.

«Хуже бы не стало» — это личное мнение.

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

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

На уровне языка прекоасно все разруливается. От вас же я просил показать, как ловить исключения, вылетевшие из конкретного блока catch. Но безрезультатно.

Теперь понял, чего Вы хотите. Да, из параметрической части блока catch никак. К слову, к конструктору это тоже относится, если аргумент не по ссылке передавать.

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

Кто вам сказал, что в C++ нельзя выпускать исключения из деструкторов? Можно и даже есть, как минимум, одна библиотека, которая это делает.

Хахаха :-) Уж не про SOCI (по-русски, СОСИ) ли ты? :-) Ахаха, там и операция «запятая» перегружена и ещё всякие причуды :-) В общем, да, есть такая библиотека с подходящим названием :-)

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

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

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

Ну пусть эксперт напишет свой Qt с объектами и исключениями.

Ну, думаю, эксперт бы и рад такое написать, но сомневаюсь что у него есть такой же бюджет, как у Qt Project :-)

Опять же, никто не заставляет пользоваться Qt. Не нравится - не ешь.

Многим нравится и без вложенных агрегатов и прочих синхрофазатронов на шаблонах :-) Поэтому и покупают и пользуются в радость :-)

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

Ну и предложите адекватную альтернативу для C++

«Разрешить» в деструкторе исключения. При исключении в процессе раскрутки стэка от другого исключения не падать, а объединять исключения в цепочки. Тогда вызов деструктора будет отличаться от условного close тем, что будет вызываться автоматически. Во всем остальном это будет обычный метод.

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

«Разрешить» в деструкторе исключения. При исключении в процессе раскрутки стэка от другого исключения не падать, а объединять исключения в цепочки. Тогда вызов деструктора будет отличаться от условного close тем, что будет вызываться автоматически.

А ты уверен, что это не будет «тормозить»? :-)

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

Уж не про SOCI (по-русски, СОСИ) ли ты?

В первую очередь про OTL.

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

«Разрешить» в деструкторе исключения. При исключении в процессе раскрутки стэка от другого исключения не падать, а объединять исключения в цепочки.

А память на эти цепочки откуда брать? И что потом делать с этими цепочками?

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

А с другой - у тебя довольно специфичный взгляд на наше ремесло.

Есть такое. Отсутствие необходимости ежедневно выдавать килобайты кода приводит к желанию оптимизировать процесс «на будущее». Отсюда и придирки к C++.

Даже в Common Lisp пришёл к тому, что «надо всё переделать»: https://github.com/Kalimehtar/advanced-readtable , https://github.com/Kalimehtar/message-oo , https://github.com/Kalimehtar/cl-std .

Если честно, я не могу припомнить ни одного случая, когда мне хотя бы теоретически надо было выбросить исключение из деструктора. Но мне важно доказать, что решение существует.

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

С одной стороны, я тебе завидую - ты сам выбираешь используемые технологии.

Начни свое дело и у тебя появится такая же возможность — выбирать используемые технологии :) Только вот когда начнешь оплачивать разработки из собственного кармана, желания связываться с маргинальщиной может сильно поубавиться ;)

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

ли даже лучше On Error в Visual Basic.

Хм... там говорится следующее: «Without an On Error statement, any run-time error that occurs is fatal...». И чем тогда отличается не перехваченное исключение в деструкторе и забытое On Error? Тем, что «an error message is displayed»? Ну да, плюсы менее «дружественные» в этом плане.

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

И чем тогда отличается не перехваченное исключение в деструкторе и забытое On Error

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

А так я могу написать On Error Resume Next перед вызовом библиотечного кода, получу утечку ресурсов, но программа при этом будет продолжать работать.

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

Даже в Common Lisp пришёл к тому, что «надо всё переделать»

Скорее ты пришёл к тому, что Racket лучше :-)

Если честно, я не могу припомнить ни одного случая, когда мне хотя бы теоретически надо было выбросить исключение из деструктора. Но мне важно доказать, что решение существует.

Ой, да везде, где требуется поставить в известность о не успешной отработке деструктора вызывающий контекст, например, завершение удалённого ресурса :-) Видишь ли, всем про RAII рассказали, про исключения напели, а из деструкторов кидать нельзя :-) Вывод сделай сам :-)

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

А с другой - у тебя довольно специфичный взгляд на наше ремесло.

Есть такое. Отсутствие необходимости ежедневно выдавать килобайты кода

Вот-вот. В «специфичный взгляд» входит и вера в характерные мифы.

Отсюда и придирки к C++.

цитата_из_всей_королевской_рати.txt

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

Я бы сказал по-другому: ограничение на исключения в деструкторах лично мне не кажется существенным.

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

Начни свое дело

Это другой скиллсет.

когда начнешь оплачивать разработки из собственного кармана, желания связываться с маргинальщиной может сильно поубавиться ;)

Маргинальность - всего лишь один из критериев оценки.

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

Скорее ты пришёл к тому, что Racket лучше

Для Racket адаптировал CLOS из Common Lisp и GUI из GTK при том, что там есть свои ОО и GUI. Самое прикольное, что все эти переделки, что в Lisp'е, что в Racket'е, я ни в одном своём проекте не использовал. Доказал, что «решение существует» и успокоился.

везде, где требуется поставить в известность о не успешной отработке деструктора вызывающий контекст, например, завершение удалённого ресурса

std::string destructor_error;

~A::A()
{
  try {
  } catch (...) {
     destructor_error = "Фигня случилась";
  }
}

{
  A a;
  ....
}
if (destructor_error == "Фигня случилась") { send_email_to_dev(); }

всем про RAII рассказали, про исключения напели, а из деструкторов кидать нельзя

Текущих абстракций в C++ вагон. Но это не значит, что ими нельзя пользоваться. Просто требуется много лишних знаний, чтобы не нарваться на внезапной падение программы или неопределённое поведение.

Можно сделать «правильный C++» выкинув совместимость. Но это уже будет не C++, а другой язык с похожим синтаксисом. Предыдущая попытка была D. Теперь вот Java, C#, Go. Но популярности нет, а поэтому нет эффективного компилятора.

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

Текущих абстракций в C++ вагон.

Как раз с деструктором в C++ таки все нормально. Проблема не в деструкторе, как в абстракции, а в том, что ее пытаются использовать не для того, для чего она задумывалась.

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

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

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

Предыдущая попытка была D. Теперь вот Java, C#, Go. Но популярности нет, а поэтому нет эффективного компилятора.

Java была несколько пораньше D. И как раз под соусом «лучшего C++». И таки стала более чем успешной попыткой.

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

Доказал, что «решение существует» и успокоился.

Исследователь :-)

Текущих абстракций в C++ вагон. Но это не значит, что ими нельзя пользоваться. Просто требуется много лишних знаний, чтобы не нарваться на внезапной падение программы или неопределённое поведение.

Такой финт с установкой флага в деструкторе, который потом можно использовать во внешнем коде:

*) возможен только если ты и есть автор деструктора или хочешь править чужую либу (но ты не хочешь, ты сам выше сказал); *) уродлив; *) подвержен ошибкам, что ты только что и продемонстрировал, т.к. std::string::operator=() в деструкторе у тебя может кидануть bad_alloc (ну не надо сказок про внутренний буфер std::string на стеке для коротких строк, благодаря которому это может не произойти) :-) Ну если кому-то нравится писать такие финты лишь бы для того, чтобы пользоваться деструкторами — флаг в руки :-)

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

Да. Более безопасный для использования.

Скорее более неудобный. Во первых, во всех «старых» либах, где noexcept не проставлен этими преимуществами пользоваться не получиться. Во вторых, все более-менее сложные функции могут выбросить, как минимум, bad_alloc. В итоге, noexcept останется для совсем простых вещей и ситуацию никак не изменит.

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

Есть такое замечательное правило: не учить других как жить. Я не понимаю, зачем требовать от С++ чего-то чего в нем не предусмотрено by design? нету, низя. всё.

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

Во вторых, оконные библиотеки вообще не очень любят out of memory и стандартное поведение у них в этой ситуации это abort()

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

Вот этот тред бреда про С++ что он якобы что-то должен он же постоянно всплывает в той или иной форме. Не должен. Он не жава, а очень усложненный ассемблер для PDP11, которым изначально и был Си.

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

Такой финт с установкой флага в деструкторе, который потом можно использовать во внешнем коде:

Ну тогда приписать деструктору noexcept(false), как сказали выше и ловить как раньше.

возможен только если ты и есть автор деструктора или хочешь править чужую либу (но ты не хочешь, ты сам выше сказал);

Задача «например, завершение удалённого ресурса» подразумевает, что ты и есть автор деструктора. Иначе нулевым пунктом станет «найти либу, в которой деструктор по данному условию кидает исключение» — боюсь, это нерешаемо.

*) уродлив

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

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

Во вторых, все более-менее сложные функции могут выбросить, как минимум, bad_alloc.

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

Хотя можно сделать свой оператор new, который этот bad_alloc бросать не будет, а будет, например, писать сообщение и приостанавливать работу программы до получения SIGCONT. Затем пытаться получить память повторно.

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

что можно например сделать в ~QWindow если оконная система отказалась удалять окно? Не буду говорит и всё тут. Как вы это «обработаете»?

В Racket останется висеть «окно» (пустой квадрат) без обработчика. Остальная программа будет продолжать штатно работать. Это лучше, чем аварийно всё завершать.

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

Ну тогда приписать деструктору noexcept(false), как сказали выше и ловить как раньше.

Нельзя так делать объект прямо или косвенно может быть в массиве, удаляемом delete[] :-)

Задача «например, завершение удалённого ресурса» подразумевает, что ты и есть автор деструктора. Иначе нулевым пунктом станет «найти либу, в которой деструктор по данному условию кидает исключение» — боюсь, это нерешаемо.

Кто о чём :-) Я сейчас об идиоме RAII, которую на деструкторах в C++ универсальной сделать нельзя :-) Значит и либу нормальную, в которой будет какой-нибудь умный указатель на удалённый ресурс, освобождаемый деструктором (не для постраховочки от ламерков, а для реального освобождения) нельзя :-) Для этого будет явный вызов функции, а не деструктор, по-любому :-)

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

Ну это тебе со Страуструпом надо переписываться :-)

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

Хотя можно сделать свой оператор new, который этот bad_alloc бросать не будет

Не надо, ибо уже есть — new(std::nothrow) Object; и все дела :-)

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

Никому он в Qt не упал ни тогда, ни сейчас — в Qt нет исключений, что отрадно, и свой ресурс менеджмент, без этих ваших смарт-поинтеров из коробки!!11

В Qt есть «точно такие же» смарт поинтеры: всякие там QScopedPointer и QSharedPointer.

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

а финализирующий поток может решить что делать, вплоть до отмены ликвидации объекта (например, записав его ещё в какой-нибудь список).

И что (и кто будет) потом с этим списком делать? Это ведь бесполезно в общем случае.

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

Он не жава, а очень усложненный ассемблер для PDP11, которым изначально и был Си.

«Чем хомячок о крысы отличается? У хомячка пиар лучше» (с).

Если бы евангелисты Си++ не расписывали его как истинно ООП язык, идеально подходящий для решения любой прикладной задачи, вопросов бы не было совсем.

А так, ООП есть, но инкапсуляция дырявая (изменение private полей влияет на клиентов библиотеки), примитивные типы не объекты; шаблоны есть, но с throw плохо дружат; исключения есть, но кроме деструкторов; замыкания есть, но контекст не удерживают (так как нет сборщика мусора).

Для усложнённого ассемблера слишком много сущностей, для прикладного языка — слишком дырявые.

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

И что (и кто будет) потом с этим списком делать? Это ведь бесполезно в общем случае.

Запись в список (или ещё куда нибудь, где ссылки не слабые) нужна просто чтобы отменить удаление. Затем по этому списку можно повторно периодически пытаться выполнить удаление ссылок на элемент. При успехе убирать из списка. Например, элемент — временный файл. В деструкторе у него — удаление этого файла. А программа запущена под оффтопиком и этот временный файл прямо сейчас удалить нельзя — его антивирус проверяет. На С++ придётся падать. Или вручную отслеживать время жизни временного файла и вызывать функцию подготовки к удалению вручную. А в финализаторе попали на блокировку файла — отменили удаление, положили в список. По таймеру проверили содержимое списка — те элементы, которые теперь удалить (их файлы с диска успешно удалились) из списка убрали.

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