С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 13.12.2019
Сообщений: 47
1

Исключения при вызове конструктора копирования

27.09.2024, 20:20. Показов 823. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день, уважаемые! вопрос по поводу исключений. Нужно ли в следующем коде, вызов метода createBike() на строчке 10, оборачивать в блок try{}?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
Bike createBike()
{
  Bike bike{};
  return move(bike);
}
 
int main()
{
 
  Bike bike2 = createBike(); // здвесь вызовется конструктор перемещения, который в теории можно кинуть исключение(ибо конструктор не помочен как noexcept). Нужно ли обернуть эту строчку кода в try-catch ?
 
  return 0;
}

я делаю move объекта bike, в методе createBike(), и тем самым вызываю конструк перемещения у объекта Bike. Конструктор перемещения класса Bike может кидать исключение(он НЕ noexcept).
P.S. Я знаю, что не стоит мувать объект bike, ибо без move, там будет NRVO, но я сделал move только ради примера. Тут акцент на обработке исключений.

Вопрос номер 2. Часто вижу, как на гитхабе, у хороших опен-сорс проектов, написанных на C++, не используется блок try-catch(точнее, мало где в коде).
Например, в std::stack есть методы, как pop() или top(). Если у std::stack вызвать метод top(), будет возвращен по значению верхний элемент стека.
Но, что если stack хранит пользовательский тип, чей конструктор копирования может кинуть исключение? то есть при вызове stack.top(), мы можем получить исключение. Но почему-то никто не оборачивает stack.pop() в конструкцию try{}.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.09.2024, 20:20
Ответы с готовыми решениями:

Ошибка при вызове конструктора копирования
Добрый день. Есть вот такой код: enum Color { RED, GREEN, BLUE, WHITE, BLACK };

Исключения при вызове throw
Предположим, что кидается исключение throw my_exception(). Конструктор my_exception - nothrow....

Зачем двоеточие при вызове конструктора?
Доброго времени суток, вот есть код, объясните зачем тут двоеточия при вызове конструктора? class...

Крашится приложение при вызове конструктора
Здравствуйте. Написал класс, а при вызове конструктора (класса Ground) приложение крашится. Где я...

5
Вездепух
Эксперт CЭксперт С++
12792 / 6669 / 1795
Регистрация: 18.10.2014
Сообщений: 16,881
27.09.2024, 22:14 2
Лучший ответ Сообщение было отмечено NewFive как решение

Решение

Цитата Сообщение от NewFive Посмотреть сообщение
Например, в std::stack есть методы, как pop() или top(). Если у std::stack вызвать метод top(), будет возвращен по значению верхний элемент стека.
Но, что если stack хранит пользовательский тип, чей конструктор копирования может кинуть исключение? то есть при вызове stack.top(), мы можем получить исключение. Но почему-то никто не оборачивает stack.pop() в конструкцию try{}.
Так (отвечая на оба вопроса), а откуда у вас возникла идея оборачивать в try{} именно непосредственно вызов бросающей исключение функции? Зачем? try{} пишется ради catch, то есть ради обработки исключений. Вы готовы здесь его обрабатывать? Если нет, то и никакого try{} здесь не нужно.

Вся идея структурной обработки исключений - это то, что обрабатывать исключения нужно именно там, где вы хотите/готовы их обрабатывать. В общем случае это будет где-то весьма и весьма далеко и намного выше по стеку вызовов, чем то место, в котором исключение возникло. А на всех более низких вложенных уровнях кода вам не нужен никакой try{}. Вам нужно лишь обеспечить корректное "сворачивание" кода (освобождение ресурсов и т.п.) если из него вдруг выбросится исключение или есть через него вдруг будет "пролетать" исключение выброшенное где-то внизу (и летящее куда-то наверх).

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

То есть тот самый try{} - он где-то есть. Но не здесь. Он сделан где-то намного выше и более огульно охватывает более крупные участки кода. А здесь, прямо на вызове stack.pop() он просто нинафиг не нужен. Что вы собрались делать в catch именно тут?

Разумеется, если try{} вообще нет ни на каком уровне, то исключение вылетит за пределы main и программа аварийно завершится. Ну так может авторы кода этого и хотели?
2
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
28.09.2024, 13:10 3
Цитата Сообщение от NewFive Посмотреть сообщение
Если у std::stack вызвать метод top(), будет возвращен по значению верхний элемент стека.
С какого дива ? Возвращается именно ссылка.

std::stack<T,Container>::top
reference top();
const_reference top() const;
0
0 / 0 / 0
Регистрация: 13.12.2019
Сообщений: 47
29.09.2024, 16:04  [ТС] 4
Спасибо больше за ответ, понял Вас.

Разумеется, если try{} вообще нет ни на каком уровне, то исключение вылетит за пределы main и программа аварийно завершится. Ну так может авторы кода этого и хотели?


А как в промышленной разработке поступают(на примере кода ниже), если было выброшено исклчюение, а у объекта была обеспечена только базовая гарантия исключений?
1. дают аварийно завершиться программе
2. ловят исключение и сами завершают программу

3. ловят исключение и продолжают выполнение программы?
К примеру, я хочу вызвать конструктор копирования у объекта vec2 типа std::vector от другого объекта vec1 типа std::vector. Но в конструкторе копирования вылетело исключение, затем были освобождены все ресурсы(чтобы объект vec1 остался в валидном/консистентном состоянии) и затем исключение из конструктора копирования было проброшено дальше. Я поймал его где-то сверху, что дальше мне делать?
1. Поймать исключение и завершить программу, написав в логах о том, что случилось
2. Поймать исключение, написать в логах о том, что случилось и дальше продолжать выполнение программы(но а если мы воспользуемся случайно vec1 ? это же неопределенное поведение программы, так делают в промышленной разработке ?).
3. Вообще не ловить исключине и дать программе аварийно завершиться.


C++
1
2
3
4
5
6
7
int main()
{
  std::vector<Bike> vec1;
  std::vector<Bike> vec2 = vec1;
 
  return 0;
}
0
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
29.09.2024, 16:32 5
NewFive, всё зависит от того можете ли вы логично обработать исключение.
Если нет, тогда логирование и аварийное завершение.
Если можете, прерываете текущую задачу, сообщаете об ошибке и продолжаете работу программы.
Это всё только логическая организация вашей программы.

Например вы редактируете какой-то документ, пытаетесь сохранить, получаете исключение, ловите сообщаете об ошибке и продолжаете работу.
И так далее.
Сама программа разбивается на подзадачи и родительский код отвечает за часть исключений, которые может обработать.
И так далее, по цепочке вверх.
1
0 / 0 / 0
Регистрация: 13.12.2019
Сообщений: 47
30.09.2024, 12:14  [ТС] 6
SmallEvil понял, спасибо!
0
30.09.2024, 12:14
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.09.2024, 12:14
Помогаю со студенческими работами здесь

Ошибка при вызове конструктора с параметрами
подскажите, почему при вызове конструктора с параметрами выдает ошибку сегментации ...

Seg fault при вызове конструктора
Здравствуйте, возникла такая проблема. Есть конструктор по умолчанию Square_matrix(), в нем...

Что за ошибка при вызове конструктора?
Компилятор ругается на строчку внутри цикла while((c = getchar()) != '\n') { q = new...

В чём отличия конструктора копирования и конструктора перемещения? Где и как их нужно использовать?
Помогите разобраться в копирующем и перемещающем конструкторах. В чём их существенное отличие и...

Запуск конструктора копирования при возврате по значению
Добрый день! Не могу разобраться как отрабатывает конструктор копирования, в случае, когда мы...

Пояснение к аргументам при вызове функции, и запрет конструктора по умолчанию
Вобщем касательно конструктора такой код: class box { public: box(int t):z(t){y=6;} void...

Ошибка при вызове конструктора basic_regex в конструкторе std::sregex_iterator
Здравствуйте! Может кто-нибудь объяснить почему, если определить переменную std::regex, а потом...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru