powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Ещё несколько вопросов начинающего программиста
60 сообщений из 60, показаны все 3 страниц
Ещё несколько вопросов начинающего программиста
    #38055682
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Несколько недель назад задавал сюда кое-какие вопросы по языку, почти на все получил ответы, за что премного благодарен. За такое длительное время выявились ещё кое-какие пробелы в знаниях, которые хотелось бы устранить.


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

11. Чем отличается size_t от int и других целочисленных типов? Для чего вообще нужен size_t?

12. Есть объект, созданный в не в куче, а у него поле, созданное в куче. Этот объект считать созданным в куче или нет? Тот же вопрос в том случае, когда объект создан в куче, а его поля -- на стеке.

13. Чем отличается operator new() от оператора new()? Один из них можно перегружать, дрйгой является встроенным, один из них вызывает другой... А зачем надобность сразу в двух похожих операторах?

14. f(new T1, new T2). Допустим, в теле функции f(...) сработало исключение. Очищается ли автоматически память, выделенная для T1 и T2? Если нет, то как её можно очистить, кроме как внутри функции f() (внутри, полагаю, кодом delete T1; delete T2;)?

15. Надо ли удалять указатели на функции подобно тому, как мы удаляем указатели на объекты?

16. При срезке обычно теряются члены дочерних классов. Допустим, дочерний класс занимал какое-то место в памяти. А куда всё девается область памяти, в которой содержатся члены дочернего класса, при преобразовании его в базовый класс, если речь именно о преобразованиях объекты, а не указателя или ссылки? Информация теряется, но происходит ли утечка памяти?

17. Если использовался размещающий new, то при исключении в конструкторе вызывается размещающий delete, который должен быть прописан, если же всё хорошо, вызывается обыкновенный delete. Верно ли, что для каждого из перегруженных new надо вызывать соответствующий перегруженный delete?

18. Верно ли, что ислючения всегда передаются по значению, даже если стоит что-то типа catch(ExepClass& ex){} или catch(ExepClass* ex){}, всё равно будет передана копия выброшенного объекта, а всякие ссылки и указатели нужны у catch только для полиморфизма? Если передана копия, то верно ли, что даже если try-catch стоят вместе (catch тут же отлавливает возможные исключения), то всё равно в catch передаётся копия выброшенного объекта?

19. Везде ли есть выравнивание?

20. Почему поля static не являются безопасными с точки зрения потоков? И верно ли, что для встроенных типов нет необходимости применять синхронизацию?

21. Что понимают под high frequency и low latency на C++? Почему плюсы считаются быстрее Java? Только из-за другого распределения памяти (в Java вся ответственность на сборщике мусора, что замедляет вычисления)? Почему другие языки не такие бытрые, как C++ и что им мешает быть быстрее?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38055861
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvango10. Правильно ли я понял, что безопасный с точки зрения исключений код -- это код, который при выбрасывании исключений в вызвавшую его функцию не даёт утечек памяти, а также не меняет состояние объекта?Выделяют три уровня безопасности по исключениям. Вы можете почитать о них в статье David-а Abrahams-а, она есть на сайте буста в разделе статей. Если коротко то в порядке "возрастания безопасности":

1. Слабое. Утечек нет. Состояние неизвестно (можно сбросить до начального и идти дальше).
2. Сильное. Утечек нет. Состояние сохранено то, что было до вызова функции выбросившей исключение.
3. Исключений гарантированно не будет.

Разные функции-(члены) и классы в целом стандартной библиотеки и других библиотек дают разные уровни безопасности по исключениям. Кроме того советую почитать статьи о моделях обработки исключений.

ayvango14. f(new T1, new T2). Допустим, в теле функции f(...) сработало исключение. Очищается ли автоматически память, выделенная для T1 и T2? Если нет, то как её можно очистить, кроме как внутри функции f() (внутри, полагаю, кодом delete T1; delete T2;)? Порядок вычисления передающихся аргументов не известен. Поэтому такой код это верный способ получить утечку при исключении во втором вызвавшемся new. Дальше надо думать головой.

ayvango16. При срезке обычно теряются члены дочерних классов. Допустим, дочерний класс занимал какое-то место в памяти. А куда всё девается область памяти, в которой содержатся члены дочернего класса, при преобразовании его в базовый класс, если речь именно о преобразованиях объекты, а не указателя или ссылки? Информация теряется, но происходит ли утечка памяти? Информация _не_ теряется если _не_ допускать банальную ошибку, объявлением деструкторов _невиртуальными_. Если у вас будут виртуальные деструкторы то апкаст ни к чему плохому не будет приводить. Если в базовом классе невиртуальный деструктор то будут утечки, связанные с невызовом деструктора потомка.

ayvango17. Если использовался размещающий new, то при исключении в конструкторе вызывается размещающий delete, который должен быть прописан, если же всё хорошо, вызывается обыкновенный delete. Верно ли, что для каждого из перегруженных new надо вызывать соответствующий перегруженный delete? Не очень понятно что вы имеете в виду под термином "размещающий delete" это наверное чепуха какая-то :). Размещающий new не имеет парного delete. Он просто размещает объект созданный вызванным им же (размещающим new) конструктором в указанной области памяти. Удалять эту память, и вызывать деструкторы объектов в ней нужно будет ручками. Учебник повнимательнее читаем, о конструкторах, об исключениях :).

Остальные вопросы в области RTFM.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38055924
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Post Scriptum

ayvango21. Что понимают под high frequency и low latency на C++? Почему плюсы считаются быстрее Java? Только из-за другого распределения памяти (в Java вся ответственность на сборщике мусора, что замедляет вычисления)? Почему другие языки не такие бытрые, как C++ и что им мешает быть быстрее? "Чтобы пятница настала быстрее, пить надо начинать в среду" (с).

C++ не быстрее Java. Java не быстрее С++. Это все спорно. Так же как плюсники любят троллить сишников примером шаблонной функции sort которая работает быстрее чем сишный qsort, и здесь можно найти контрпримеры.

Дело в другом. В коренном различии отношения к программисту, и в конечном итоге целях проектирования языка.

С++ никогда не навязывал и хочется надеяться не будет навязывать определенную технологию программисту. Он всегда оставляет право выбора. "Дизайн и эволюция С++" это манифест языка свободы.

Java, C# - решают за вас. Ты должен использовать сборщик мусора, а как он будет работать я беру на себя. Ты не должен использовать прямой доступ к памяти, а то наделаешь кучу ошибок. Ты не должен применять множественное наследование, потому что эта [marketing on]неправильная модель[marketing off] (и плевать что это неестественно, просто ты туп как сибирский валенок и не сможешь использовать его правильно). Ты не должен знать расположение объектов, мы их меняем на дню раза три. Ты не должен знать как работает низлежащее оборудование, а должен использовать средства параллельности которые в каждом случае выбраны за тебя. Вот тебе простенький "идеальный" виртуальный мирок живи в нем, а с реальностью мы уж как-то сами. Ленись, не развивайся, учи маркетинг вместо инженерии. The Matrix has you (c).

Я не говорю что виртуальная машина упрощающая реальность это плохо. Это очень крутой механизм для применения (отличный пример встраиваемая lua или javascript). Плохо когда тебя "закубовывают в рай".
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056064
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvango11. Чем отличается size_t от int и других целочисленных типов? Для чего вообще нужен size_t?

У меня в _stddef.h написано:
typedef unsigned int size_t;
Так что это не отдельный тип, а int.

ayvango15. Надо ли удалять указатели на функции подобно тому, как мы удаляем указатели на объекты?

Интересно, зачем удалять указатели? Обычно они определяются, как переменные и обнуляются после удаления объекта.
Код: plaintext
1.
2.
3.
4.
5.
      int *a;
      a = new int;
      *a = 5;
      delete a;
      a = NULL;


Или вы имели в виду такой пример?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
      int **a;
      a = new (int *);
      *a = new int;
      **a = 5;
      delete *a;
      delete a;
      a = NULL;


Конечно, же можно и указатели по new создавать, но обычно так создают массивы указателей, что-то вроде char** argv.
Всё, что мы создаём при помощи new должно быть удалено. Правило такое.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056112
Abstraction
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня в _stddef.h написано:
typedef unsigned int size_t;
Так что это не отдельный тип, а int.Нет. Это тип, который в Вашем случае совпадает с int.
А вообще, это тип, в который гарантированно влезет размер любого массива. Также именно этот тип возвращает sizeof.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056126
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AbstractionУ меня в _stddef.h написано:
typedef unsigned int size_t;
Так что это не отдельный тип, а int.Нет. Это тип, который в Вашем случае совпадает с int.
А вообще, это тип, в который гарантированно влезет размер любого массива. Также именно этот тип возвращает sizeof.

то есть вы хотите сказать, что в стандарте языка С++ есть тип size_t ?

у меня и в хелпе написано, что это просто беззнаковый инт:
size_t
typedef ui-type size_t;
The type is the unsigned integer type ui-type of an object that you declare to store the result of the sizeof operator.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056142
Abstraction
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yatha,

В working draft, выдаваемый Гуглом на первой позиции по запросу C++ standard, это раздел 5.3.3, п.6. Ссылка на актуальный стандарт у меня опять куда-то потерялась.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056237
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AbstractionYatha,

В working draft, выдаваемый Гуглом на первой позиции по запросу C++ standard, это раздел 5.3.3, п.6. Ссылка на актуальный стандарт у меня опять куда-то потерялась.

в пункте 5.3.3 п.6 написано
The result is a constant of type std::size_t. [ Note: std::size_t is defined in the standard header <cstddef>
(18.1). —end note ]

Об этом я, в общем-то, и говорил. Что он определён дефайном и не является отдельным типом.
А вот в пункте 3.9.1 Fundamental types такого типа нету. Написано, что есть 5 целых типов:

2 There are five signed integer types : “signed char”, “short int”, “int”, “long int” and “long long int”.
In this list, each type provides at least as much storage as those preceding it in the list. Plain ints have the natural size
suggested by the architecture of the execution environment44); the other signed integer types are provided to meet special
needs.
3 For each of the signed integer types, there exists a corresponding (but different) unsigned integer type: “unsigned
char”, “unsigned short int”, “unsigned int”, “unsigned long int”, and “unsigned long long int”,
each of which occupies the same amount of storage and has the same alignment requirements (3.9) as the corresponding
signed integer type45); that is, each signed integer type has the same object representation as its corresponding unsigned
integer type. The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned
integer type, and the value representation of each corresponding signed/unsigned type shall be the same.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056268
sherzod_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sherzod_ayvango17. Если использовался размещающий new, то при исключении в конструкторе вызывается размещающий delete, который должен быть прописан, если же всё хорошо, вызывается обыкновенный delete. Верно ли, что для каждого из перегруженных new надо вызывать соответствующий перегруженный delete? Не очень понятно что вы имеете в виду под термином "размещающий delete" это наверное чепуха какая-то :). Размещающий new не имеет парного delete. Он просто размещает объект созданный вызванным им же (размещающим new) конструктором в указанной области памяти. Удалять эту память, и вызывать деструкторы объектов в ней нужно будет ручками. Учебник повнимательнее читаем, о конструкторах, об исключениях :). Видимо мне самому впору перечитывать учебник. Действительно такой термин имеет место быть. "placement form of operator delete." Судя по описанию placement delete это не совсем то о чем можно подумать. Ушел изучать...
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056304
Abstraction
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yatha,

авторОб этом я, в общем-то, и говорил. Что он определён дефайном и не является отдельным типом.Он не фундаментальный тип. Но он тип, который (согласно стандарту) должен быть, и в отношении его гарантируется то, что не гарантируется в отношении int (это отвечая на вопрос ТС). Чем он реально определён - лично я считал бы это вопросом реализации.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056372
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Abstraction,
формально, вы правы и это другой тип.
Другое дело, что С++ это не Ада и, если написать int в качестве параметра функции вместо size_t, то даже warning не будети всё скомпилится. То же самое, если вместо NULL написать 0.
А чем определён, так это, действительно, может зависеть от реализации. Ведь стандартом даже не определены размеры char, int, long int и long long int и они могут быть одинаковы по размерам.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056406
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YathaAbstraction,
формально, вы правы и это другой тип.
Другое дело, что С++ это не Ада и, если написать int в качестве параметра функции вместо size_t, то даже warning не будети всё скомпилится.варнинг как раз будет, потому что читайте внимательно: typedef unsigned int size_t; так что это не int, а без знаковый int, что, конечно, правильно.
>> То же самое, если вместо NULL написать 0.
ну а NULL - это вообще дефайн. Не рекомендуется этим макросом пользоваться, насколько я помню.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056424
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ayvango11. Чем отличается size_t от int и других целочисленных типов? Для чего вообще нужен size_t?

14. f(new T1, new T2). Допустим, в теле функции f(...) сработало исключение. Очищается ли автоматически память, выделенная для T1 и T2? Если нет, то как её можно очистить, кроме как внутри функции f() (внутри, полагаю, кодом delete T1; delete T2;)?

20. Почему поля static не являются безопасными с точки зрения потоков? И верно ли, что для встроенных типов нет необходимости применять синхронизацию?


11. size_t - это беззнаковый тип для хранения размеров объектов и индексов массивов. Если вы будете вместо него для этих целей использовать int/unsigned int/long и т.д. то у вас программа может работать на одной платформе, а на другой может не работать.
Например у вас код:
Код: plaintext
1.
for (int i = 0; i < vect.size(); ++i)...


На 32битной платформе он сработает (поскольку вероятность выделения там объекта размером >2GB почти равна нулю) а на 64-битной будет переполнение для объектов >2GB.
Есть еще знаковый вариант - ptrdiff_t, который предназначен для хранения разницы между двумя указателями.
В принципе размеры size_t, ptrdiff_t, void* всегда равны и этот размер зависит от платормы и равен битности ее адресного пространства (32 бита - uint32_t, 64 бита - uint64_t).

14. Есть вполне безопасное решение этой проблемы - оборачивать каждый new в смартуказатель.

20. Поля static - глобальные, поэтому к ним всегда возможен доступ из разных потоков.
Для встроенных типов необходимость синхронизации зависит от платформы.
Например long long, double на 32-битной платформе неатомарные.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056479
32vs64
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AbstractionУ меня в _stddef.h написано:
typedef unsigned int size_t;
Так что это не отдельный тип, а int.Нет. Это тип, который в Вашем случае совпадает с int.
А вообще, это тип, в который гарантированно влезет размер любого массива. Также именно этот тип возвращает sizeof.
Добавлю, что насколько я помню если компилируешь под 32 бита, то и size_t 32 битный unsigned int.
А если под 64 бита, то size_t 64 битный unsigned long long.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056506
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychну а NULL - это вообще дефайн. Не рекомендуется этим макросом пользоваться, насколько я помню.

Насколько я помню с точностью наоборот — не рекомендуется пользоваться 0 вместо NULL. Так как нет гарантии что на какой-нибудь платформе адрес 0 не используется для каких-нибудь своих целей.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056529
nullptr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Yathaegorychну а NULL - это вообще дефайн. Не рекомендуется этим макросом пользоваться, насколько я помню.

Насколько я помню с точностью наоборот — не рекомендуется пользоваться 0 вместо NULL. Так как нет гарантии что на какой-нибудь платформе адрес 0 не используется для каких-нибудь своих целей.
Он наверное имеет ввиду использовать nullptr, который реализован почти во всех компиляторах, но не во всех.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056547
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yatha wrote:
>> Насколько я помню с точностью наоборот — не рекомендуется пользоваться 0 вместо NULL. Так как нет гарантии что на какой-нибудь платформе адрес 0 не используется для каких-нибудь своих целей
да-да-да, это пишут изобретатели макроса NULL. Но мы то можем ведь и подумать самостоятельно. Ведь на самом деле, если у тебя в библиотечном заголовке написано #define NULL 0 то по фигу, что ты будешь писать в своём коде, 0 или NULL - один хрен, если "адрес 0 используется платформой для каких-нибудь своих целей" - то макрос NULL не спасёт. Единственное, что тут может помочь, это:

>> Он наверное имеет ввиду использовать nullptr, который реализован почти во всех компиляторах, но не во всех.
nullptr - добро, в отличие от NULL, дефайн любой может переобъявить, и вообще никогда не узнаешь, с каких хренов всё вдруг начало падать.
Единственно, что на старых компиляторах, включая студию от 2008 года выпуска, он не реализован, приходится мучаться с нулями и нулами.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056575
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychYatha wrote:
>> Насколько я помню с точностью наоборот — не рекомендуется пользоваться 0 вместо NULL. Так как нет гарантии что на какой-нибудь платформе адрес 0 не используется для каких-нибудь своих целей
да-да-да, это пишут изобретатели макроса NULL. Но мы то можем ведь и подумать самостоятельно. Ведь на самом деле, если у тебя в библиотечном заголовке написано #define NULL 0 то по фигу, что ты будешь писать в своём коде, 0 или NULL - один хрен, если "адрес 0 используется платформой для каких-нибудь своих целей" - то макрос NULL не спасёт.

Изобретатели макроса NULL — это как раз создатели языка Си :) В стандарте используется как раз NULL, а не 0.
А если "адрес 0 используется платформой для каких-нибудь своих целей" то макрос NULL как раз таки спасёт, ибо для этой платформы он будет определён, например, как #define NULL 0xffff и код останется переносимым. А с 0 вместо NULL на такой платформе будут косяки.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056582
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullptrОн наверное имеет ввиду использовать nullptr, который реализован почти во всех компиляторах, но не во всех.

Я пишу на C++ Builder XE. Там он не реализован.

nullptr
Description

Reserved for future use. nullptr is a literal that can be assigned to any pointer to indicate the pointer doesn't point to anything.


Warning: C++Builder does not implement nullptr but does treat it as a keyword when the -Ax compiler flag is set. Do not use nullptr as an identifier.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056599
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YathaВ стандарте используется как раз NULL, а не 0.да, согласен. Но nullptr - всё равно лучше )))
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056604
Фотография Yatha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychЕдинственное, что тут может помочь, это:

>> Он наверное имеет ввиду использовать nullptr, который реализован почти во всех компиляторах, но не во всех.
nullptr - добро, в отличие от NULL, дефайн любой может переобъявить, и вообще никогда не узнаешь, с каких хренов всё вдруг начало падать.
Единственно, что на старых компиляторах, включая студию от 2008 года выпуска, он не реализован, приходится мучаться с нулями и нулами.

Хочу открыть страшную-престрашную тайну. Можно и nullptr переопределить.
Например, #define nullptr 100.
Да что там nullptr. Можно и int переопределить,
например, #define int char,
а потом думать, почему не компилится.
Ну, и классика жанра, конечно:
#define true false
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38056762
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullptr появился в С++11.
В С и С++2003 и раннее его нет.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057137
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор10. Правильно ли я понял, что безопасный с точки зрения исключений код -- это код, который при выбрасывании исключений в вызвавшую его функцию не даёт утечек памяти, а также не меняет состояние объекта?

Да, чаще всего ещё и без требования неизменности состояния объекта.

автор11. Чем отличается size_t от int и других целочисленных типов? Для чего вообще нужен size_t?

Это специальный тип для хранения размера объекта.
Дело в том, что размеры int long и void* не определены стандартом и в принципе везде разные.
А size_t, который должен хранить любую разницу между двумя void* -- вообще был бы не понятно какого типа, если бы не было size_t в явном виде.

автор12. Есть объект, созданный не в куче, а у него поле, созданное в куче.
Этот объект считать созданным в куче или нет?

Нет, этот объект создан не в куче (на стеке, в глобальной памяти или ещё как).

авторТот же вопрос в том случае, когда объект создан в куче, а его поля -- на стеке.

Это -- ошибка проектирования Объект при этом создан естественно в куче. Только как он будет жить при выходе из скопа автоматических объектов, на которые он ссылается -- не понятно. Такое иногда допустимо, если он ссылается на автоматические переменные в функцие main, например.

автор13. Чем отличается operator new() от оператора new()? Один из них можно перегружать, дрйгой является встроенным, один из них вызывает другой... А зачем надобность сразу в двух похожих операторах?

Видимо, речь идёт о обычном new и placement new ? Уточни...

автор14. f(new T1, new T2). Допустим, в теле функции f(...) сработало исключение. Очищается ли автоматически память, выделенная для T1 и T2? Если нет, то как её можно очистить, кроме как внутри функции f() (внутри, полагаю, кодом delete T1; delete T2;)?

Тонкий момент. Точно не знаю.
Видимо, не должна очищаться.
При аналогичном почти случае внутри инициализаторов конструктора очищается автоматом.

автор15. Надо ли удалять указатели на функции подобно тому, как мы удаляем указатели на объекты?

Надо, если ты выделял функцию динамически, с помощью new. поскольку это сделать в С++ (пока по крайней мере) нельзя,
то это "надо" не наступает никогда.

автор16. При срезке обычно теряются члены дочерних классов. Допустим, дочерний класс занимал какое-то место в памяти. А куда всё девается область памяти, в которой содержатся члены дочернего класса, при преобразовании его в базовый класс, если речь именно о преобразованиях объекты, а не указателя или ссылки? Информация теряется, но происходит ли утечка памяти?

Срезка происходит только при копировании самого объекта. При присваивании, при возврате объета по значению.
При этом обычно объекты находятся: исходный -- всё равно где и не меняется, результирующий -- на стеке (при возврате), либо там, где его определили при присваивании. В любом случае проблем с памятью не возникает и утечек никаких нет.

автор17. Если использовался размещающий new, то при исключении в конструкторе вызывается размещающий delete, который должен быть прописан, если же всё хорошо, вызывается обыкновенный delete. Верно ли, что для каждого из перегруженных new надо вызывать соответствующий перегруженный delete?

Нет, на сколько я понимаю вопрос. new может быть наперегружен дофига как, фактически ты можешь указать у new любое кол-во любых аргументов. А delete этим всем new будет соответствовать только один.

автор18. Верно ли, что ислючения всегда передаются по значению,

Куда передаются ? Исключения -- это обычные объекты, если ты их используешь по-обычному, они передаются так же, как объекты во всех других случаях (слово "объект" тут означает не только объекты классов, но и объекты встроенных типов С++).
Если при выкидывании исключения имеется в виду в вопросе -- тогда ровно так они передаются, как идёт выкидывание.
Если кидается сам объект, происходит передача по значению, если адрес выкидываетсы -- то по указателю.
Т.е. с учётом семантики указателей можно сказать, что передаётся при TROW объект всегда по значению (т.е. если выкидывается указатель, то по значению передаётся указатель).

автордаже если стоит что-то типа catch(ExepClass& ex){} или catch(ExepClass* ex){}, всё равно будет передана копия выброшенного объекта, а всякие ссылки и указатели нужны у catch только для полиморфизма?

Нет, это совсем неверно. Если будет кидаться объект по значению, а ты будешь ловить указатель, то просто данный catch ничего не поймает. И наоборот, если кидается указатель, а ловится ссылка или значение, тоже не поймаешь. Ловля по значению и по ссылке отличается лиш тем, что при ловле по значению происходит дополнительное копирование (и возможно срезка).

авторЕсли передана копия, то верно ли, что даже если try-catch стоят вместе (catch тут же отлавливает возможные исключения), то всё равно в catch передаётся копия выброшенного объекта?

Да.

автор19. Везде ли есть выравнивание?

Стандарт не определяет это. Так что ничего об этом сказать нельзя. Где-то оно есть, где-то его нет.
Сказать, что оно есть везде, нельзя. Сказать, что его нигде нет -- тоже.
автор20. Почему поля static не являются безопасными с точки зрения потоков?

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

авторИ верно ли, что для встроенных типов нет необходимости применять синхронизацию?

Нет. В корне неверно.

автор21. Что понимают под high frequency и low latency на C++?

Это не имеет отношения к С++, выходит за его рамки. Не имеет смысл обсуждать.

авторПочему плюсы считаются быстрее Java?

Код: plaintext
(дальше пошёл свободный трёп на произвольную тему, к С++ не относящийся).

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

авторТолько из-за другого распределения памяти (в Java вся ответственность на сборщике мусора, что замедляет вычисления)?

Вот тут есть один момент, который существенно влияет на "почему плюсы считаются быстрее Java". В Java часто (почти всегда) перераспределение памяти может возникать в любой момент работы программы. Ну вообще просто тупо почти всегда. Поэтому её не любят создатели ПО, которое расчитано на маленькие задержки, или почти или полностью realtime. Ну действительно -- ты тут считашь что-то, считаеш, торопишся, ещё милисекудна, ещё пол милисекунды осталось -- а тут бац -- и сборщик мусора заработал.
В С++ выделение и освобождение памяти всегда детерминировано, предсказуемо. Когда оно произойдёт -- всегда известно.
Поэтому такое ПО писать легче.

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

Ну, это уж вообще философский вопрос -- наверное, надо "спрашивать" у тех языков об этом.
Языков много, все разные... Есть языки ничуть не менее быстрые чем С++, С например, Паскаль, Fortran. Да и много других.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057142
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sherzod_ayvango14. f(new T1, new T2). Допустим, в теле функции f(...) сработало исключение. Очищается ли автоматически память, выделенная для T1 и T2? Если нет, то как её можно очистить, кроме как внутри функции f() (внутри, полагаю, кодом delete T1; delete T2;)? Порядок вычисления передающихся аргументов не известен. Поэтому такой код это верный способ получить утечку при исключении во втором вызвавшемся new. Дальше надо думать головой.

ayvango16. При срезке обычно теряются члены дочерних классов. Допустим, дочерний класс занимал какое-то место в памяти. А куда всё девается область памяти, в которой содержатся члены дочернего класса, при преобразовании его в базовый класс, если речь именно о преобразованиях объекты, а не указателя или ссылки? Информация теряется, но происходит ли утечка памяти? Информация _не_ теряется если _не_ допускать банальную ошибку, объявлением деструкторов _невиртуальными_. Если у вас будут виртуальные деструкторы то апкаст ни к чему плохому не будет приводить. Если в базовом классе невиртуальный деструктор то будут утечки, связанные с невызовом деструктора потомка.



Видимо, тут sherzod_ абсолютно не понимает, о чём речь идёт.
При чём там порядок вычислений в первом случае и виртуальные деструкторы во втором -- вообще не понятно.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057143
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sherzod_C++ не быстрее Java. Java не быстрее С++.
...
Плохо когда тебя "закубовывают в рай".

+1
Классный пост! sherzod_ - молодец !
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057148
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sherzod_ Действительно такой термин имеет место быть. "placement form of operator delete." Судя по описанию placement delete это не совсем то о чем можно подумать. Ушел изучать...

Вкратце --
placement new -- способ вызвать конструктор,
placement delete -- способ вызвать деструктор
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057150
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
32vs64Добавлю, что насколько я помню если компилируешь под 32 бита, то и size_t 32 битный unsigned int.
А если под 64 бита, то size_t 64 битный unsigned long long.

Что, в общем, очень логично
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057237
MasterZivавторТот же вопрос в том случае, когда объект создан в куче, а его поля -- на стеке.

Это -- ошибка проектирования Объект при этом создан естественно в куче. Только как он будет жить при выходе из скопа автоматических объектов, на которые он ссылается -- не понятно. Такое иногда допустимо, если он ссылается на автоматические переменные в функцие main, например.
Да это не то что ошибка, это в принципе не возможно - создать объект в куче, а его члены данные на стеке. Оно уже все будет в куче.


автор14. f(new T1, new T2). Допустим, в теле функции f(...) сработало исключение. Очищается ли автоматически память, выделенная для T1 и T2? Если нет, то как её можно очистить, кроме как внутри функции f() (внутри, полагаю, кодом delete T1; delete T2;)?
В любом случае этот код не правилен. Конечно объекты сами не будут удаляться.
Даже с использованием shared_ptr
boost::shared_ptr BestPractices

Видимо, тут sherzod_ абсолютно не понимает, о чём речь идёт.
При чём там порядок вычислений в первом случае и виртуальные деструкторы во втором -- вообще не понятно.

А он видимо имеет ввиду вариант с shared_ptr по ссылке выше:
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057238
MasterZivТонкий момент. Точно не знаю.
Видимо, не должна очищаться.
При аналогичном почти случае внутри инициализаторов конструктора очищается автоматом.

Имеется ввиду если в списке инициализации конструктора класса выделяется динамическая память в куче, то при выбросе исключения до того как объект будет создан и выполниться конструктор, эта динамическая память освобождается?


MasterZivавтор18. Верно ли, что ислючения всегда передаются по значению,

автордаже если стоит что-то типа catch(ExepClass& ex){} или catch(ExepClass* ex){}, всё равно будет передана копия выброшенного объекта, а всякие ссылки и указатели нужны у catch только для полиморфизма?

Нет, это совсем неверно. Если будет кидаться объект по значению, а ты будешь ловить указатель, то просто данный catch ничего не поймает. И наоборот, если кидается указатель, а ловится ссылка или значение, тоже не поймаешь. Ловля по значению и по ссылке отличается лиш тем, что при ловле по значению происходит дополнительное копирование (и возможно срезка).

А есть здесь какой-то best practice, допустим кидать объект по значению, а ловить его полиморфно по ссылке базового класса, и уже по этой ссылке вызывать виртуальную функцию которая и обработает это исключение?


MasterZivавторЕсли передана копия, то верно ли, что даже если try-catch стоят вместе (catch тут же отлавливает возможные исключения), то всё равно в catch передаётся копия выброшенного объекта?

Да.
А RVO или move constructor тут не работают?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057269
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptrВ любом случае этот код не правилен. Конечно объекты сами не будут удаляться.
Даже с использованием shared_ptr
boost::shared_ptr BestPractices

shared_ptr надо создавать через make_shared<..>(...) и тогда все ок.


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

А он видимо имеет ввиду вариант с shared_ptr по ссылке выше:
Кстати shared_ptr (по крайней мере бустовскому) не нужен виртуальный деструктор для нормального удаления потомка.
Код: plaintext
1.
2.
boost::shared_ptr<parent> p(new child);
p.reset(); // вызовется деструктор ~child
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057274
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptrА есть здесь какой-то best practice, допустим кидать объект по значению, а ловить его полиморфно по ссылке базового класса, и уже по этой ссылке вызывать виртуальную функцию которая и обработает это исключение?
...
А RVO или move constructor тут не работают?
Кидать исключение по значению и ловить по ссылке - это в принципе единственный разумный вариант.
Если вы будете кидать указатели (new) - то надо не только ловить но и удалять .
А если кидать и ловить по значению - то будет никому ненужное копирование, которого нет при ловле по ссылке, и поэтому никакой оптимизации тут не нужно.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057278
Anatoly Moskovskyвариант с shared_ptrВ любом случае этот код не правилен. Конечно объекты сами не будут удаляться.
Даже с использованием shared_ptr
boost::shared_ptr BestPractices

shared_ptr надо создавать через make_shared<..>(...) и тогда все ок.
А std::make_shared<..>(...) в новом стандарте принимает и передает в конструктор любое количество параметров через вариадические шаблоны?

Anatoly Moskovsky
При чём там порядок вычислений в первом случае и виртуальные деструкторы во втором -- вообще не понятно.

А он видимо имеет ввиду вариант с shared_ptr по ссылке выше:
Кстати shared_ptr (по крайней мере бустовскому) не нужен виртуальный деструктор для нормального удаления потомка.
Код: plaintext
1.
2.
boost::shared_ptr<parent> p(new child);
p.reset(); // вызовется деструктор ~child


А как и в чем он начальный тип запоминает?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057279
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptrА std::make_shared<..>(...) в новом стандарте принимает и передает в конструктор любое количество параметров через вариадические шаблоны?

Ну наверно, иначе зачем тогда вариадик нужен :)
Код: plaintext
1.
2.
boost::shared_ptr<parent> p(new child);
p.reset(); // вызовется деструктор ~child


А как и в чем он начальный тип запоминает?
Конструктор у boost::shared_ptr шаблонный, он выводит и сохраняет тип аргумента внутри shared_ptr (в так называемом deleter, который юзер и сам может предоставлять указателю, если надо)
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057474
Шарповец
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivавторТолько из-за другого распределения памяти (в Java вся ответственность на сборщике мусора, что замедляет вычисления)?

Вот тут есть один момент, который существенно влияет на "почему плюсы считаются быстрее Java". В Java часто (почти всегда) перераспределение памяти может возникать в любой момент работы программы. Ну вообще просто тупо почти всегда. Поэтому её не любят создатели ПО, которое расчитано на маленькие задержки, или почти или полностью realtime. Ну действительно -- ты тут считашь что-то, считаеш, торопишся, ещё милисекудна, ещё пол милисекунды осталось -- а тут бац -- и сборщик мусора заработал.
В С++ выделение и освобождение памяти всегда детерминировано, предсказуемо. Когда оно произойдёт -- всегда известно.
Поэтому такое ПО писать легче.
А как с этим дела обстоят в С# или в .NET в целом? Так же?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38057622
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Best practice for exception handling in C++:
- throw by value
- catch by reference, in ascending order of generality (least general types go first)

- кидать про значению
- ловить по ссылке, в порядке увеличения отрешенности типа, т.е. конкретные типы сначала, обобщенные — потом.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38058136
MasterZivBest practice for exception handling in C++:
- throw by value
- catch by reference, in ascending order of generality (least general types go first)

- кидать про значению
- ловить по ссылке, в порядке увеличения отрешенности типа, т.е. конкретные типы сначала, обобщенные — потом.
А это из какой книги?
И обработчик исключения держать в виртуальной функции самого этого же исключения - это хороший вариант?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38058161
Anatoly Moskovsky
Код: plaintext
1.
2.
boost::shared_ptr<parent> p(new child);
p.reset(); // вызовется деструктор ~child


А как и в чем он начальный тип запоминает?
Конструктор у boost::shared_ptr шаблонный, он выводит и сохраняет тип аргумента внутри shared_ptr (в так называемом deleter, который юзер и сам может предоставлять указателю, если надо)
А, там шаблонный функтор-deleter на который в shared_ptr полиморфно храниться указатель базового типа.

Т.е. shared_ptr хранит 3 указателя: на объект, на счетчик и на функтор-deleter. И если использовать make_shared<..>(...) то в куче выделяется память один раз, а если не использовать, то 3 раза?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38058172
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptrИ обработчик исключения держать в виртуальной функции самого этого же исключения - это хороший вариант?
Это бессмысленный вариант.
Все равно что сказать: вот у меня функция F() но присваивать ее результат вы можете только в переменную A.
Если бы объекту исключения было известно как самого себя обрабатывать, то смысла бросать исключения нет - сразу бы его и обрабатывали.
Но обычно ничего такого не известно.
Одно и то же исключение в разном контексте обрабатывается по-разному. Поэтому невозможно в исключении держать обработчик.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38058180
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptrТ.е. shared_ptr хранит 3 указателя: на объект, на счетчик и на функтор-deleter. И если использовать make_shared<..>(...) то в куче выделяется память один раз, а если не использовать, то 3 раза?
deleter хранится со счетчиком в одном объекте.

make_shared да, оптимизирует выделение памяти под вспомогательные объекты.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38058426
Anatoly Moskovskyвариант с shared_ptrИ обработчик исключения держать в виртуальной функции самого этого же исключения - это хороший вариант?
Это бессмысленный вариант.
Все равно что сказать: вот у меня функция F() но присваивать ее результат вы можете только в переменную A.
Если бы объекту исключения было известно как самого себя обрабатывать, то смысла бросать исключения нет - сразу бы его и обрабатывали.
Но обычно ничего такого не известно.
Одно и то же исключение в разном контексте обрабатывается по-разному. Поэтому невозможно в исключении держать обработчик.
Конечно всю обработку в самом исключении не сделаешь, но запись в лог-файл через потокобезопасный синглтон сделать можно.
Хотя наверное лучше писать в лог в конструкторе базового класса исключения заодно используя __LINE__, __FILE__, __DATE__, __TIME__, __func__ , т.к. он как раз для всех наследуемых исключений выполнится в месте самого исключения.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38058491
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptrХотя наверное лучше писать в лог в конструкторе базового класса исключения заодно используя __LINE__, __FILE__, __DATE__, __TIME__, __func__ , т.к. он как раз для всех наследуемых исключений выполнится в месте самого исключения.
Если вы это имеете в виду
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
struct E
{
    E()
    {
        cerr << __FUNCTION__ << endl;
    }
};

throw E();


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

Чтобы правильно работало, надо само создание объекта исключения оборачивать в макрос и из него передавать все эти атрибуты вызывающего кода через аргументы конструктора.
А с макросами уже не так приятно иметь дело.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38058884
Anatoly Moskovskyвариант с shared_ptrХотя наверное лучше писать в лог в конструкторе базового класса исключения заодно используя __LINE__, __FILE__, __DATE__, __TIME__, __func__ , т.к. он как раз для всех наследуемых исключений выполнится в месте самого исключения.
Если вы это имеете в виду
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
struct E
{
    E()
    {
        cerr << __FUNCTION__ << endl;
    }
};

throw E();


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

Чтобы правильно работало, надо само создание объекта исключения оборачивать в макрос и из него передавать все эти атрибуты вызывающего кода через аргументы конструктора.
А с макросами уже не так приятно иметь дело.
Да, фактически надо будет что-то типа:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
 
 
struct stream2string {
    template<class T>
    stream2string& operator<< (T const& arg) {
        buf_stream << arg;
        return *this;
    }
    std::string str() const {
        return buf_stream.str();
    }
protected:
    std::stringstream buf_stream;
};
 
void exception_catch() {
    try {
        throw;   
    } catch(std::runtime_error const& e) {
        std::cerr << "runtime_error: " << e.what() << std::endl;
    } catch(std::exception const& e) {
        std::cerr << "exception: " << e.what() << std::endl;
    } catch(...) {
        std::cerr << "unknown error!" << std::endl;
    }    
}
 
#define THROW_PLACE (stream2string() << __FILE__ << ": " << __LINE__ << ": " << __DATE__ << " " << __TIME__ << ", " << __FUNCTION__ << ": ").str()
 
 
int main() {
 
    try {
        throw std::runtime_error(THROW_PLACE);
    } catch(...) {
        exception_catch();
    }
 
    
    return 0;
}



Макросы конечно не приятно, но а какой другой выход если хочется в логах как можно точнее знать место исключения?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38058897
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptr
Код: plaintext
1.
2.
3.
4.
5.
    try {
        throw std::runtime_error(THROW_PLACE);
    } catch(...) {
        exception_catch();
    }



Бррр...
Надеюсь такой изврат никогда не увидеть в коде с которым мне придется работать.

Если вы уже используете макрос при вызове исключения, то в нем и логируйте. Откладывать логирование до поимки и потом tot ловить ... это антипаттерн (даже два).

Код: plaintext
1.
2.
3.
4.
5.
    try {
        THROW_PLACE(std::runtime_error, message);  // раскрывается в {log(message + place); throw std::runtime_error(message + place);}
    } catch(std::runtime_error&) {
        ...
    }
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38058955
Anatoly Moskovskyвариант с shared_ptr
Код: plaintext
1.
2.
3.
4.
5.
    try {
        throw std::runtime_error(THROW_PLACE);
    } catch(...) {
        exception_catch();
    }



Бррр...
Надеюсь такой изврат никогда не увидеть в коде с которым мне придется работать.

Если вы уже используете макрос при вызове исключения, то в нем и логируйте. Откладывать логирование до поимки и потом tot ловить ... это антипаттерн (даже два).

Код: plaintext
1.
2.
3.
4.
5.
    try {
        THROW_PLACE(std::runtime_error, message);  // раскрывается в {log(message + place); throw std::runtime_error(message + place);}
    } catch(std::runtime_error&) {
        ...
    }


Смотрите, ваш подход будет логировать только те исключения, которые кидаете именно вы.
А если есть:
- сторонняя dll-библиотека, которая кидает исключения
- чужой cpp-код, который кидает исключения
- исключения которые кидают std::dynamic_cast, new и т.д.
То как вы предложите логировать эти исключения?


А какие именно 2 проблемы (2 антипатерна) вот такого подхода?
Ну, помимо того, что в каждом catch придется писать log_exception();
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    // Так много различных ловлю водном try чисто для примера.
    try {
        throw std::runtime_error(THROW_PLACE + message);
    } catch(std::runtime_error const& e) { 
        log_exception();
        // обработка std::runtime_error
    } catch(std::bad_alloc const& e) { 
        log_exception();
        // обработка std::bad_alloc 
    } catch(std::exception const& e) {
        log_exception();
        // обработка std::exception
    } catch(исключения из dll) {
        log_exception();
        // обработка исключения из dll
    } catch(исключения из сторонних cpp) {
        log_exception();
        // обработка исключения из сторонних cpp
    } catch(...) {
        log_exception();
        // обработка unknown exception
    }
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38059110
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot вариант с shared_ptr]MasterZivBest practice for exception handling in C++:
- throw by value
- catch by reference, in ascending order of generality (least general types go first)

- кидать про значению
- ловить по ссылке, в порядке увеличения отрешенности типа, т.е. конкретные типы сначала, обобщенные — потом.
А это из какой книги?

Ну из многих. Напр. Из Меерса.


И обработчик исключения держать в виртуальной функции самого этого же исключения - это хороший вариант?

Это все равно.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38059841
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptr,

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

При этом я не отрицаю что в программе на самом верхнем уровне вложенности кода (обычно это тело цикла событий потока) может быть перехватчик всех непойманных исключений с логированием того факта что исключение не поймано.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38059943
Anatoly Moskovskyвариант с shared_ptr,

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

При этом я не отрицаю что в программе на самом верхнем уровне вложенности кода (обычно это тело цикла событий потока) может быть перехватчик всех непойманных исключений с логированием того факта что исключение не поймано.
В принципе со всем согласен.
Но действительно есть места, где необходимо обязательно ловить исключения и либо тут же их обрабатывать, либо логировать место их первой поимки и посылать их для обработки выше. Например в перечисленных мною же случаях при исключениях выходящих из библиотек, чужого кода и из std.
Если внутри самой библиотеки/чужого кода исключение не поймано и выходит наружу, значит это уже ошибка, а не рабочий момент. И желательно знать где оно произошло. Аналогично и с bad_cast, bad_alloc и т.д.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38059997
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptrИ желательно знать где оно произошло. Аналогично и с bad_cast, bad_alloc и т.д.
Узнать место можно только при бросании исключения.
Если вы споймали bad_alloc или другое чужое исключение вы никак не узнаете откуда оно брошено.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38060100
Anatoly Moskovskyвариант с shared_ptrИ желательно знать где оно произошло. Аналогично и с bad_cast, bad_alloc и т.д.
Узнать место можно только при бросании исключения.
Если вы споймали bad_alloc или другое чужое исключение вы никак не узнаете откуда оно брошено.
Локализую это место насколько можно точнее и выбор будет из 3 new, а не из 100.
Тоже касается и чужих dll/cpp, по крайней мере я пойму из какой именно библиотеки и функции исключение. А по DATE TIME я пойму, когда компилился исходник вызывающий чужой код и найду эту версию в SVN/GIT.

Зачастую если проект является не заказным решением, а коробочным продуктом, то невозможно ни получить от клиента адекватное описание бага, ни получить из-за коммерческой тайны входные данные воспроизводящие баг, ни отдебажить пошагово на стороне клиента. Так что лог и в лучшем случае дампы - это все, что от них можно получить.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38060997
Можно как-то числовую константу __LINE__ взять в кавычки, чтобы не выдумывать всякие stream2string().
Что-то типа:
#define THROW_PLACE std::string() + __FILE__ + ": " + "__LINE__"
А то тут в кавычках подставится не значение константы __LINE__, а сама надпись.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38061003
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptr,

Код: plaintext
1.
... + boost::lexical_cast<std::string>(__LINE__) + ...
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38061341
Anatoly Moskovskyвариант с shared_ptr,

Код: plaintext
1.
... + boost::lexical_cast<std::string>(__LINE__) + ...


Это то да, стандартное универсальное решение.
А проще нет?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38061367
Mozok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptr,

я не понял, вот это имелось в виду?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38061403
Mozokвариант с shared_ptr,

я не понял, вот это имелось в виду?
Да :)
В GCC по крайней мере вот так:
Код: plaintext
1.
2.
3.
4.
#define xstr(s) str(s)
#define str(s) #s
     
#define THROW_PLACE std::string() + __FILE__ + ": " + xstr(__LINE__) + ": " + __DATE__ + " " + __TIME__ + ", " + __FUNCTION__ + ": "
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38061656
Anatoly MoskovskyОткладывать логирование до поимки и потом tot ловить ... это антипаттерн (даже два).

Код: plaintext
1.
2.
3.
4.
5.
    try {
        THROW_PLACE(std::runtime_error, message);  // раскрывается в {log(message + place); throw std::runtime_error(message + place);}
    } catch(std::runtime_error&) {
        ...
    }


А чем хуже или лучше вариант с логированием исключений следующим образом:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
#include <iostream>
#include <string>
#include <stdexcept>

#define xstr(s) str(s)
#define str(s) #s
#define THROW_PLACE std::string() + __FILE__ + ": " + xstr(__LINE__) + ": " + __DATE__ + " " + __TIME__ + ", " + __FUNCTION__ + ": "


struct log_exception : exception {
    log_exception(std::string const& msg) : exception(msg) {
        log(msg);
    }
}

struct nolog_exception : exception {
    nolog_exception(std::string const& msg) : exception(msg) {
        show_message(msg);
    }
}

struct critical_exception : log_exception {
    critical_exception(std::string const& msg) : log_exception(msg) { }
}

struct lost_packet_exception : nolog_exception {
    lost_packet_exception(std::string const& msg) : nolog_exception(msg) { }
}


void func() {
    try {
        // ...
        std::throw(critical_exception(THROW_PLACE + "crush data file"));    // is logged
        // ...
    } catch (critical_exception const& ) {
        
    }
    
    
    try {
        // ...
        std::throw(lost_packet_exception(THROW_PLACE + "connection failed"));   // not is logged
        // ...
    } catch (lost_packet_exception const& ) {
        
    }    
    
}
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38061758
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptr,

Из конструктора предка лучше не логировать, т.к. там виртуальная what() наследника еще недоступна.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38061783
Anatoly Moskovskyвариант с shared_ptr,

Из конструктора предка лучше не логировать, т.к. там виртуальная what() наследника еще недоступна.
А яж сообщение не из what() беру, а непосредственно из параметра конструктора, или желательно брать из what()?
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38061820
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вариант с shared_ptr,

Это конечно вам решать как это делать.
Но, это вы сейчас не вызываете виртуальных ф-й в конструкторе, а кто после вас с этим кодом будет работать неизвестно.

Ну и если вы наследуете от std::exception то надо наверно как минимум предоставлять реализацию what().
Я бы исключения с сообщениями наследовал от std::runtime_error - там уже есть реализация what() которая берет сообщение из аргумента конструктора.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38061987
ayvango
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YathaИнтересно, зачем удалять указатели? Обычно они определяются, как переменные и обнуляются после удаления объекта.
Под удалением я имел ввиду применение оператора delete для удаления объектов, на который они указывают.
Так нужно ли применять delete f, если f -- указатель на функцию?

P.S. спасибо всем ответившим на вопросы. Некоторые из них остались без ответа, если что -- пишите.
...
Рейтинг: 0 / 0
Ещё несколько вопросов начинающего программиста
    #38062063
не нужно
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ayvangoYathaИнтересно, зачем удалять указатели? Обычно они определяются, как переменные и обнуляются после удаления объекта.
Под удалением я имел ввиду применение оператора delete для удаления объектов, на который они указывают.
Так нужно ли применять delete f, если f -- указатель на функцию?

P.S. спасибо всем ответившим на вопросы. Некоторые из них остались без ответа, если что -- пишите.
Нет, не нужно. Потому что создать динамически экземпляр функции не возможно.
...
Рейтинг: 0 / 0
60 сообщений из 60, показаны все 3 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / Ещё несколько вопросов начинающего программиста
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]