powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Ещё несколько вопросов начинающего программиста
25 сообщений из 60, страница 2 из 3
Ещё несколько вопросов начинающего программиста
    #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
25 сообщений из 60, страница 2 из 3
Форумы / C++ [игнор отключен] [закрыт для гостей] / Ещё несколько вопросов начинающего программиста
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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