C++11: возвращает ли объект по значению никогда не генерирует исключения, когда определяется ctor перемещения?

В C++11 и более поздних стандартах гарантируется, что ctor копии (возможно, выбрасывающий исключение) не вызывается при возврате объекта класса по значению из функции - при условии, что ctor перемещения определен для этого класса? Фон: Предположим,

struct X {
   X() {}
   X(const X&) {/* code that might throw exceptions */}
   X(X&&) {/* code that never throws exceptions */}
   ...
};

а также

X my_func(some_type& t)
{
   X x;
   // code that modifies t and x but never throws exceptions
   return x;
}

Теперь, например, такое выражение, как

some_other_func(my_func(t));

никогда не выбрасывать исключения (т.е. это гарантировано?) при условии, что функция some_other_func(const X&) не бросает исключения? А что если подпись some_other_func мы some_other_func(X)?

2 ответа

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

Неявно дефолтные функции (т.е. автоматически предоставляемые операции копирования и перемещения) обычно следуют логике: объявлено как noexcept тогда и только тогда, когда все функции, которые он вызывает, noexcept,

Исключения никогда не генерируются спонтанно в правильно сформированной программе C++, которая только оправдывает определенное поведение.

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

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

Что вы должны сделать, это пометить X(X&&) а также X() как noexceptи эта конкретная проблема уходит.

Несмотря на это, ваш точный код не выдаст, если some_other_function не берет X но вместо этого тип, созданный из X и эта операция может бросить, или тело some_other_function мог бы бросить.

Другие вопросы по тегам