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++ деструкторы?

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

Expected может сохранить любой exception

Насколько я могу судить, он умеет сохранять не только исключения. Но если только их - он ублюдочное ненужно.

Rust вроде не умеет(тип «ошибки» указан в типе)

Ну, судя по тому, что Expected - это тупо написанный вручную sum type, я сомневаюсь, что он умеет что-то, чего не умеют sum types из Rust.

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

Насколько я могу судить, он умеет сохранять не только исключения.

Результат или исключение.

Ну, судя по тому, что Expected - это тупо написанный вручную sum type, я сомневаюсь, что он умеет что-то, чего не умеют sum types из Rust.

Тип исключения/ошибки во время компиляции далеко не всегда возможно корректно определить(смотри проверяемые исключения в java и почему от них фактически все отказались).

Expected сохранит любое исключение.

чего не умеют sum types из Rust

В rust есть аналог std::exception_ptr?

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

Насколько я могу судить, он умеет сохранять не только исключения.

Результат или исключение.

Я не нашел ограничения на тип ошибочного объекта. Куда смотреть?

В rust есть аналог std::exception_ptr?

В Rust нет исключений, так что ХЗ, можно ли там сделать аналог exception_ptr. Но в Rust есть Any, который возвращается из panic!.

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

Это можно расширить до «или неудачное освобождение случается крайне редко и/или не несёт особых проблем», что несколько расширяет зону применения.

Думаешь стоит? Вот тут в теме крестовики про файлы говорили...

Значения ошибок

Распространена порочная практика — не проверять возвращаемое значение close(). В результате можно упустить критическое условие, приводящее к ошибке, так как подобные ошибки, связанные с отложенными операциями, могут не проявиться вплоть до момента, как о них сообщит close(). При таком отказе вы можете встретить несколько возможных значений errno. Кроме EBADF (заданный дескриптор файла оказался недопустимым), наиболее важ ным значением ошибки является EIO. Оно соответствует низкоуровневой ошибке вводавывода, которая может быть никак не связана с самим актом закрытия.

RAII в теории должен быть ортоганален проблемам с исключениями внутри деструктора. На практике же в C++ мы не сможем и файл гарантированно попытаться закрыть и информацию об ошибке выше передать. Печаль. В случае надобности приходится делать руками, как в Си. Вот и спрашивается в задачнике, а стоит ли вообще использовать C++, если в реальности для качественного ПО придется писать как в Си?

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

На практике же в C++ мы не сможем и файл гарантированно попытаться закрыть

Гарантированно попытаться - сможете. Гарантированно закрыть - нет, но Си++ в этом не виноват ровно никак.

В случае надобности приходится делать руками, как в Си

Как в Си - не приходится. Вызов деструктора гарантирован.

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

Так у них вижуал бейсик отличным выбором получается

А почему, думаешь, он до сих пор живой? Для скриптов самое то. А для крупных проектов язык с разбросом max/min больше чем C++ никуда не годится.

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

Как в Си - не приходится. Вызов деструктора гарантирован.

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

int foo(...)
{
    ...
    if ((rc = close(fd)) == -1) {
        ...
        return -1;
    }
    ...
}
anonymous
()
Ответ на: комментарий от anonymous

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

Ты не можешь передать ошибку выше с помощью деструктора. А в общем случае - можешь.

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

как делается (делалось бы) в том же ракете. Можно минимальный пример?

(require ffi/unsafe/custodian ffi/unsafe)

;;; safe-open 
;;;    name : path-string? 
;;;    handle-exceptions : (any input-port? -> any) 
;;;    -> input-port?
;;; handle-exceptions -- функция, которая получает исключение и открытый файл и пытается с ними что-то сделать
;;; 
(define (safe-open name handle-exceptions)
  (define s (open-input-file-name) 
  ;;; регистрируем закрытие при выходе из программы 
  (register-custodian-shutdown	 
     s
     (lambda (s) (close-input-port s))
     #:at-exit #t)
  ;;; регистрируем деструктор
  (register-finalize
     s
     (lambda (s) 
       (with-handlers ([(lambda (e) #t) ;; ловим всё
                        (lmabda (e) (handle-exceptions e s)])
         (close-input-port s))))
  s)
monk ★★★★★
()
Ответ на: комментарий от DarkEld3r

Во первых, я повторюсь: эктеншн методы. Даже в шарпе дошли до понимания, что это бывает удобно.

Не спорю, но надо провести черту, где удобно сделать эксшеншен/свободную функцию, а где сделать насоедование. Каждый архитектор решает для себя сам где эта черта. Остальные споры - это лишь споры о вкусовщине.

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

Во вторых, ты говоришь лозунгами.

Все тут говорят лозунгами. В c# можно унаслоедоваться от классов из фреймвфорка, от коллекций-женериков, а можно добавить экстеншены. Есть свобода, в с++ свободы нет. Разговор был лишь о том, что в c++ наследование от stl клссов черевато выстрелом в ногу из гранатомета. Я говорю, что такое наследование может пригодиться в зависимости от разной философии ведения архитектуры проекта. Но в С++ по сути нам зарещают один из путей. Я лишь говорю, что это неправильно. В c# никто не мешает тебе добавить эктеншен-методы, или внешние классы для сеарилизации любого типа. Но в c# вполне можно отнаследоваться и реализовать все внутри класса (более того для этого даже интерфейсы уже подготовлены!). Я лишь радею за снятие исторических ограничений. Да, я понимаю, что для этого потребуется глобальный пересмотр stl, но если в том же c++20 примут модули он так и так потребуется...

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

Это наводит порядок, отделяет мухи от котлет. Если жестко следовать SOLID то надо нагородить кучу абстракций, кучу клссов, кучу кода. Буквально недавно надо было уже на текущем проекте добавить банальное логирование в базу в нову таблицу с двумя полями, но для этого в текущей архитекутуре надо было сделать около 5 новых классов, столько же новых интерфейсов (мы о .net говорим сейчас). Первая мысль нормального человека - «а зачем это? это какое то нагорождение сущностей? Это все пишется в две строчки кода!». Но потом ты погружаешься в проект и понимаешь, что когда надо что-то резко изменить или написать юнит-тест это очень хорошо, что все через абстрации, наследование и прочую муть. Еще раз - это все вопрос вкусовщины. О ней спорить бесполезно. Каждый архитектор/тимлид сам проводит черту, сам определят поход. И это правильно. Я против ограничений на один из подходов.

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

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

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

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

Так вкусовщины или технологичности (юнит-тесты или устойчивость к изменениям - это технологичность, если что).

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

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

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

Ты не можешь передать ошибку выше с помощью деструктора. А в общем случае - можешь.

Да, руками. Как в Си. RAII в C++ завязан на деструкторы.

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

Да, руками. Как в Си. RAII в C++ завязан на деструкторы.

И ты считаешь, что это причина писать на Си вместо Си++?

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

Так получается, что при ближайшем рассмотрении большая часть языковых достоинств C++ перед C в реальных задачах уходят на второй, если ни на третий, план. Даже RAII(не самая плохая задумка), что и показывает рассматриваемый пример.

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

Есть свобода, в с++ свободы нет.

Это не так. Когда ты создаешь тип, тебе нужно определиться, полиморфный он или нет. Разве в C# поддерживается наследование структур? Так вот контейнеры в stl скорее структуры в терминах C#. И это правильно, на мой взгляд.

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

Ерунду вы сейчас пишете.

int foo(...)
{
    ...
    if ((rc = some_other_op()) == -1)
        return -1;

    if ((rc = close(fd)) == -1) {
        ...
        return -1;
    }
    ...
}
И проблем с таким кодом в C намного больше, чем с невозможностью сообщить об ошибке в деструкторе класса в C++.

И даже в случае, если в C программируют в стиле goto cleanup, получается ничем не лучше:

int foo() {
  FILE * f1 = NULL, * f2 = NULL, * f3 = NULL;
  int rc = -1;

  if( !(f1 = fopen(...) ) goto cleanup;
  if( !(f2 = fopen(...) ) goto cleanup;
  if( !(f3 = fopen(...) ) goto cleanup;
  ...
  if( (rc = some_other_op()) == -1 ) goto cleanup;
  ...
cleanup:
  if( f3 ) {
    if( (rc = fclose(f3)) == EOF )
       ? // what can we do here?!!!
  }
  ...
  return rc;
}

И после этого говорить, что достоинства C++ уходят на какой-то там план... Ну нормально, чо.

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

Так покажите православную обработку ошибок от close на C++

Покажите, что вы считаете православной обработкой ошибок.

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

И проблем с таким кодом в C намного больше, чем с невозможностью сообщить об ошибке в деструкторе класса в C++.

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

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

Чтобы мы могли обработать ошибку в close и ему подобных методах и передать информацию вызывающему коду.

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

Чтобы мы могли обработать ошибку в close и ему подобных методах и передать информацию вызывающему коду.

Наша песня хороша... Каким образом передать? Через Expected/result, исключение, код возрата, логгер, еще что? Никто не запрещает методу close, например, кинуть исключение. Если твоя функция не хочет его пропустить (из-за try в деструкторе), то никто не мешает ей поставить try, сделать что-то и потом вручную дернуть этот метод. При этом опустим практический смысл передачи этой информации, когда объект уже был удален и толку от этого знания никакого нет, т.к. ничего уже сделать нельзя. Потому, если и надо такую ситуацию обрабатывать то именно так, как я написал - в самой функции.

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

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

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

Каким образом передать?

Как вам угодно. Я понимаю, что крестовики не привыкли обрабатывать ошибки close и других подобных функций, но это неправильно. Покажите, как вы бы обрабатывали close в C++. Все. Больше ничего говорить и показывать не надо сейчас. Оправдываться, задавать «умные» наводящие вопросы тоже. Просто код на C++.

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

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

По сравнению с чем? Боле конкретно: по сравнению с какими возможностями Си?

Даже RAII(не самая плохая задумка), что и показывает рассматриваемый пример.

Рассматриваемый пример не показывает ничего, кроме ломающей новости о том, что close может вернуть ошибку (хотя это специально упоминалось еще в «UNIX - универсальная среда программирования»).

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

Я не пишу в таком стиле, почему я должен это показывать?

У меня, кстати, вряд ли будут три открытых файла одновременно в одной функции. Попахивает говнокодом. Но допустим.

int foo(error_t * err) { int fd1 = 0, fd2 = 0, fd3 = 0; int rc = -1, cleanup_rc = -1; error_t * last_err = err;

if((fd1 = open(...) == -1) goto end; if((fd2 = open(...) == -1) goto close_fd1; if((fd3 = open(...) == -1) goto close_fd2;

...

if( (rc = some_other_op()) == -1 ) goto cleanup;

...

cleanup: close_fd3: if ((cleanup_rc = close(fd3)) == -1) { ... rc = -1; } close_fd2: if ((cleanup_rc = close(fd2)) == -1) { ... rc = -1; } close_fd1: if ((cleanup_rc = close(fd1)) == -1) { ... rc = -1; } end: return rc; }

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

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

Я не пишу в таком стиле, почему я должен это показывать?

У меня, кстати, вряд ли будут три открытых файла одновременно в одной функции. Попахивает говнокодом. Но допустим.

int foo() {
  int fd1 = 0, fd2 = 0, fd3 = 0;
  int rc = -1, cleanup_rc = -1;
  error_t * last_err = err;

  if((fd1 = open(...) == -1) goto end;
  if((fd2 = open(...) == -1) goto close_fd1;
  if((fd3 = open(...) == -1) goto close_fd2;

  ...

  if( (rc = some_other_op()) == -1 ) goto cleanup;

  ...

cleanup:
close_fd3:
  if ((cleanup_rc = close(fd3)) == -1) {
      ...
      rc = -1;
  }
close_fd2:
  if ((cleanup_rc = close(fd2)) == -1) {
      ...
      rc = -1;
  }
close_fd1:
  if ((cleanup_rc = close(fd1)) == -1) {
      ...
      rc = -1;
  }
end:
  return rc;
}

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

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

Просто код на C++

Что случилось? Где же RAII?

Надеюсь, ты ответишь тем же и продемонстрируешь код на Си?

Он будет таким же(если мы логируем на этом уровне). Или же прокинем ошибку выше.

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

Надеюсь, ты ответишь тем же и продемонстрируешь код на Си?

Он будет таким же(если мы логируем на этом уровне)

Прекрасно, здесь у Си и Си++ паритет. Теперь покажи мне Си-аналог примерно такого кода:

unique_ptr<int> p = make_unique<int>(123);

С автоматическим освобождением при return и, желательно, longjmp (как ближайшем аналоге исключений в Си).

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

Полагаю, ваш код должен выглядеть вот так:

int foo(error_t * err) {
  int fd1 = 0, fd2 = 0, fd3 = 0; int rc = -1, cleanup_rc = -1;
  error_t * last_err = err;

  if((fd1 = open(...) == -1) goto end;
  if((fd2 = open(...) == -1) goto close_fd1;
  if((fd3 = open(...) == -1) goto close_fd2;
...
  if( (rc = some_other_op()) == -1 ) goto cleanup;
...
cleanup:
close_fd3: if ((cleanup_rc = close(fd3)) == -1) { ... rc = -1; }
close_fd2: if ((cleanup_rc = close(fd2)) == -1) { ... rc = -1; }
close_fd1: if ((cleanup_rc = close(fd1)) == -1) { ... rc = -1; }
end:
  return rc;
}
Все правильно?

Если так, то вы только что явили образцовый образчик теплового лампового говнокодика на чистой сишечке, который неустойчив к правкам. У вас, например, изрядная часть логики завязана на последовательность меток после cleanup и на корректность последовательность goto. Стоит, к примеру, поменять местами открытие файлов и лови потом ошибки.

Ну и главное: куда вы засовываете информацию об ошибках при вызове close?

eao197 ★★★★★
()
Ответ на: комментарий от tailgunner
int * p = NULL;
...
p = malloc(sizeof(int));
if (!p) {
    return -1;
}
// ...
free(p);

С автоматическим освобождением при return

int * p __attribute__ ((__cleanup__(free))) = NULL;
p = malloc(sizeof(int));
...

и, желательно, longjmp (как ближайшем аналоге исключений в Си).

Нет, не желательно.

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

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

Глупое заявление.

Оправдываться, задавать «умные» наводящие вопросы тоже.

И еще глупее. Эти вопросы нужны, чтоб понять какую именно ситуацию ты хочешь рассмотреть. В С++ во-многих проектах, например, вообще не используются исключения. А где-то наоборот - они повсеместно.

Покажите, как вы бы обрабатывали close в C++

Если это std::fstream, то просто:

f.close();
if( !f )
....

Если что-то с исключениями:

// Что-то делаем, при желании пробрасываем исключение наверх
try {
}
catch(....) {
}

// Закрываем, обрабатываем ошибку или пробрасываем исключение
try {
    f.close();
}
catch(.....) {
   ...
}
anonymous
()
Ответ на: комментарий от anonymous

int * p __attribute__ ((__cleanup__(free))) = NULL;

p = malloc(sizeof(int));

Итого, даже в лучшем случае кода в 2 раза больше и компилятором он не проверяется (в sizeof можно передать что угодно). И кстати, это не код на Си - это код на нестандартном расширении Си.

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

Если так, то вы только что явили образцовый образчик теплового лампового говнокодика на чистой сишечке

бла-бла-бла

Стоит, к примеру, поменять местами открытие файлов и лови потом ошибки

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

куда вы засовываете информацию об ошибках при вызове close?

Куда захочу. Т.е. куда мне будет нужно в рамках архитектуры моей системы. Системные функции пишут в errno все, но они и не открывают по 100500 ресурсов за раз. Возможно, я сделаю что-то подобное. Возможно сделаю свой тип для информации об ошибках. Возможно, я сделаю связный список ошибок. Зависит от.

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

Итого, даже в лучшем случае кода в 2 раза больше

На фоне кода логики это будет почти незаметно.

И кстати, это не код на Си - это код на нестандартном расширении Си.

Мы на linux.org.ru. gcc и clang поддерживают. Для оффтопика можно сделать тоже самое на __try __finally.

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

Глупое заявление.

Ну так лор же. Придерживаюсь традиций.

Эти вопросы нужны, чтоб понять какую именно ситуацию ты хочешь рассмотреть

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

В С++ во-многих проектах, например, вообще не используются исключения. А где-то наоборот - они повсеместно.

Я знаю. Сам пишу на крестах ;) И давно.

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

Итого, даже в лучшем случае кода в 2 раза больше

На фоне кода логики это будет почти незаметно.

Если писать логику в таком же дубовом Си-стиле - да.

Для оффтопика можно сделать тоже самое на __try __finally.

А для Си++ не надо делать ничего.

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

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

Ну так покажите хотя бы один похожий на рабочий вариант. А то это все разговоры в пользу бедных. На C++ несложно сделать что-то вроде:

class my_special_closer {
  not_null<std::FILE *> what_;
  error_collector & collector_;
public :
  my_special_closer(not_null<std::FILE *> what, error_collector & collector)
    : what_(what), collector_(collector) {}
  ~my_special_closer() {
    if( EOF == std::fclose(what_.get()) )
      collector_.push_error(...);
  }
};
...
int foo(error_collector & collector) {
  std::FILE * f1;
  if( !(f1 = std::fopen(...)) ) return -1;
  my_special_closer f1_closer(f1, collector);

  std::FILE * f2;
  if( !(f2 = std::fopen(...)) ) return -1;
  my_special_closer f2_closer(f2, collector);

  std::FILE * f3;
  if( !(f3 = std::fopen(...)) ) return -1;
  my_special_closer f3_closer(f3, collector);
...
  if( -1 == some_other_op() ) return -1;
...
}
Что очень похоже на Go-шный defer или на D-шный at_scope(exit). И ничего у вас не потеряется.

eao197 ★★★★★
()
Последнее исправление: eao197 (всего исправлений: 1)

Не нужны ебийомать! Прекратите засирать трекер этим вопросом, деструктивные!

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

Отлично. Примерно такой код я и ожидал в этой теме увидеть. А то одна болтовня=)

Теперь возвращаемся к RAII и исключениям(не забываем о них)...

В вашем коде могут быть исключения. Да, файлы закроются(будет сделана попытка), да, ошибки «соберутся». Но если collector лежит/доступен только по стеку ближе к нам, чем обработчик исключения, то мы таки потеряем данные. В этом и заключается проблема C++, которая в этой теме поднимается... C++ плохо дружит сам с собой. Вы можете сделать замечательную систему на C++, но вряд ли вам в этом поможет весь язык как одно целое. Какие-то фичи будут помогать, с какими-то, наоборот, придется бороться и обходить. Если вы имеете большой опыт работы с другими языками, то понимаете, что C++ выделяется в этом плане не в лучшую сторону. Нет целостности. Нет стиля. Множество возможностей отстрелить себе ногу по самые гланды. Последствия от ошибок, как правило, более серьезные, чем в системах на Си.

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

Извините, но вы сейчас написали полную ахинею. Начиная от совершенно мутных «Но если collector лежит/доступен только по стеку ближе к нам, чем обработчик исключения, то мы таки потеряем данные.» (как будто в C будет как-то иначе) и заканчивая эпичным «что C++ выделяется в этом плане не в лучшую сторону».

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

Может Rust через какое-то время таким конкурентом и станет. Но уж явно не чистая сишечка.

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

Надо за контекстом разговора следить

Ну так лор же. Придерживаюсь традиций. (c)

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

Да, если не устраивает дефолтная их обработка в деструкторе. Это какой-нибудь fstream не знает что делать в таких случаях, а в своих классах можно напрямую дергать обработчики, родителей, запускать таски и пр. и пр.

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

как будто в C будет как-то иначе

В Си нет исключений.

С++ — это инструмент

Си - инструмент. С++ - скорее набор инструментов, плохо между собой согласующихся.

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

Да, если не устраивает дефолтная их обработка в деструкторе

Так она почти никогда не устраивает. По крайней мере в тех задачах, где C/C++ по делу используют.

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

Но если уж он подходит для некоторой предметной области, то вменяемых конкурентов у него там нет.

Тут даже соглашусь. Лично для меня C++ приятнее С. И на нем я работаю продуктивнее.

Но уж явно не чистая сишечка.

По факту это C++ все никак не может вытеснить С. За столько-то лет.

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