Сообщение Re[10]: Exception safe T Stack::pop() ? от 21.08.2018 14:19
Изменено 21.08.2018 14:21 N. I.
Re[10]: Exception safe T Stack::pop() ?
uzhas:
U>ты хочешь сказать, что из-за того, что в свежем стандарте появилось больше безопасных вариантов вызова метода T pop() проблема как бы исчезла?
U>она не исчезла, т.к. "опасные" варианты всё еще остались.
"Опасные" варианты использования всегда можно придумать, в том числе и для пары top и pop:
Если POTENTIALLY_THROWING_EXPRESSION кинет исключение, то на вершине стеке, возможно, останется лежать мусорный объект, а полезное значение топового элемента может быть "утеряно".
U>в стандарте нет таких примеров, что вот вызывайте std::vector::at (для примера) только в одну строчку с присваиванием, иначе мы не даем гарантии на безопасность к исключениям.
Тебе возможные варианты кривого использования std::vector::at привести, что ли?
U>это ерунда какая-то, слишком уж много нюансов надо держать в голове
Мда, это ж какой мегамозг надо иметь, чтоб держать в голове два действия: перемещение/копирование элемента и его удаление... С таким rocket science далеко не каждый справится.
U>что ты скажешь про такие варианты вызова?
U>
U>в каких случаях C++17 нас защищает, а в каких у нас уже будут проблемы при исключениях при копировании?
Если T — это кошерный тип с небросающим перемещающим конструктором и небросающим перемещающим оператором присваивания, то копирования T тут нигде не будет (внутренности f1 — f4 не рассматриваем). В этом случае возможностей C++11 уже достаточно.
В случае, если для возврата значения из pop используется потенциально бросающее копирование, C++17 даёт возможность сделать отложенный вызов деструктора для топового элемента при условии, что исключение брошено не было. Дальше при инициализации параметра t функции f1 C++17 обеспечивает guaranteed copy elision.
U>ты хочешь сказать, что из-за того, что в свежем стандарте появилось больше безопасных вариантов вызова метода T pop() проблема как бы исчезла?
U>она не исчезла, т.к. "опасные" варианты всё еще остались.
"Опасные" варианты использования всегда можно придумать, в том числе и для пары top и pop:
T t = std::move(stack.top());
POTENTIALLY_THROWING_EXPRESSION;
use_value(t);
stack.pop();
Если POTENTIALLY_THROWING_EXPRESSION кинет исключение, то на вершине стеке, возможно, останется лежать мусорный объект, а полезное значение топового элемента может быть "утеряно".
U>в стандарте нет таких примеров, что вот вызывайте std::vector::at (для примера) только в одну строчку с присваиванием, иначе мы не даем гарантии на безопасность к исключениям.
Тебе возможные варианты кривого использования std::vector::at привести, что ли?
U>это ерунда какая-то, слишком уж много нюансов надо держать в голове
Мда, это ж какой мегамозг надо иметь, чтоб держать в голове два действия: перемещение/копирование элемента и его удаление... С таким rocket science далеко не каждый справится.
U>что ты скажешь про такие варианты вызова?
U>
void f1(T t);
void f2(const T& t);
void f3(T&& t);
template<typename U>
void f4(U&& t) {}
int main() {
T t;
t = stack.pop(); // 1
f1(stack.pop()); //2
f2(stack.pop()); //3
f3(stack.pop()); //4
f4(stack.pop()); //5
}
U>в каких случаях C++17 нас защищает, а в каких у нас уже будут проблемы при исключениях при копировании?
Если T — это кошерный тип с небросающим перемещающим конструктором и небросающим перемещающим оператором присваивания, то копирования T тут нигде не будет (внутренности f1 — f4 не рассматриваем). В этом случае возможностей C++11 уже достаточно.
В случае, если для возврата значения из pop используется потенциально бросающее копирование, C++17 даёт возможность сделать отложенный вызов деструктора для топового элемента при условии, что исключение брошено не было. Дальше при инициализации параметра t функции f1 C++17 обеспечивает guaranteed copy elision.
Re[10]: Exception safe T Stack::pop() ?
uzhas:
U>ты хочешь сказать, что из-за того, что в свежем стандарте появилось больше безопасных вариантов вызова метода T pop() проблема как бы исчезла?
U>она не исчезла, т.к. "опасные" варианты всё еще остались.
"Опасные" варианты использования всегда можно придумать, в том числе и для пары top и pop:
Если POTENTIALLY_THROWING_EXPRESSION кинет исключение, то на вершине стека, возможно, останется лежать мусорный объект, а полезное значение топового элемента может быть "утеряно".
U>в стандарте нет таких примеров, что вот вызывайте std::vector::at (для примера) только в одну строчку с присваиванием, иначе мы не даем гарантии на безопасность к исключениям.
Тебе возможные варианты кривого использования std::vector::at привести, что ли?
U>это ерунда какая-то, слишком уж много нюансов надо держать в голове
Мда, это ж какой мегамозг надо иметь, чтоб держать в голове два действия: перемещение/копирование элемента и его удаление... С таким rocket science далеко не каждый справится.
U>что ты скажешь про такие варианты вызова?
U>
U>в каких случаях C++17 нас защищает, а в каких у нас уже будут проблемы при исключениях при копировании?
Если T — это кошерный тип с небросающим перемещающим конструктором и небросающим перемещающим оператором присваивания, то копирования T тут нигде не будет (внутренности f1 — f4 не рассматриваем). В этом случае возможностей C++11 уже достаточно.
В случае, если для возврата значения из pop используется потенциально бросающее копирование, C++17 даёт возможность сделать отложенный вызов деструктора для топового элемента при условии, что исключение брошено не было. Дальше при инициализации параметра t функции f1 C++17 обеспечивает guaranteed copy elision.
U>ты хочешь сказать, что из-за того, что в свежем стандарте появилось больше безопасных вариантов вызова метода T pop() проблема как бы исчезла?
U>она не исчезла, т.к. "опасные" варианты всё еще остались.
"Опасные" варианты использования всегда можно придумать, в том числе и для пары top и pop:
T t = std::move(stack.top());
POTENTIALLY_THROWING_EXPRESSION;
use_value(t);
stack.pop();
Если POTENTIALLY_THROWING_EXPRESSION кинет исключение, то на вершине стека, возможно, останется лежать мусорный объект, а полезное значение топового элемента может быть "утеряно".
U>в стандарте нет таких примеров, что вот вызывайте std::vector::at (для примера) только в одну строчку с присваиванием, иначе мы не даем гарантии на безопасность к исключениям.
Тебе возможные варианты кривого использования std::vector::at привести, что ли?
U>это ерунда какая-то, слишком уж много нюансов надо держать в голове
Мда, это ж какой мегамозг надо иметь, чтоб держать в голове два действия: перемещение/копирование элемента и его удаление... С таким rocket science далеко не каждый справится.
U>что ты скажешь про такие варианты вызова?
U>
void f1(T t);
void f2(const T& t);
void f3(T&& t);
template<typename U>
void f4(U&& t) {}
int main() {
T t;
t = stack.pop(); // 1
f1(stack.pop()); //2
f2(stack.pop()); //3
f3(stack.pop()); //4
f4(stack.pop()); //5
}
U>в каких случаях C++17 нас защищает, а в каких у нас уже будут проблемы при исключениях при копировании?
Если T — это кошерный тип с небросающим перемещающим конструктором и небросающим перемещающим оператором присваивания, то копирования T тут нигде не будет (внутренности f1 — f4 не рассматриваем). В этом случае возможностей C++11 уже достаточно.
В случае, если для возврата значения из pop используется потенциально бросающее копирование, C++17 даёт возможность сделать отложенный вызов деструктора для топового элемента при условии, что исключение брошено не было. Дальше при инициализации параметра t функции f1 C++17 обеспечивает guaranteed copy elision.