Бросить исключение и вернуть результат из функции - PullRequest
9 голосов
/ 04 марта 2012

Я только изучаю C ++ и хотел бы выдать исключение, но тогда результат моей функции будет неопределенным ???

 std::vector<myStruct> extract_notworking(std::vector<myStruct>& avec){
        std::vector<myStruct> result;

        if (avec.size() == 0)
            //throw domain_error("Cannot operate on empty vector!");
            //Cannot use exception for it would yield undefined result
            return result;

        //do something here
        //...
        return result;
    }

Что мне делать?Вернуть пустой вектор?Что произойдет, если я сгенерирую исключение для получателя возвращаемого значения?

Ответы [ 3 ]

11 голосов
/ 04 марта 2012

Когда вы генерируете исключение, функция останавливается там, и выполнение переходит к месту, где было поймано исключение. Ваша функция ничего не возвращает, потому что функция вообще не возвращает.

Вы можете просто сделать

if (avec.empty())
    throw domain_error("Cannot operate on empty vector!");

И ваша функция там выйдет.

Обратите внимание, что вам не нужно беспокоиться о возвращаемом значении («Как функция может ничего не возвращать?» И т. Д.), Потому что вы не можете получить доступ к возвращаемому значению функции, которая сгенерировала (и не уловила) исключение, даже если вы пытаетесь.

Так, например, если вы сделаете

try {
    std::vector<myStruct> vec;

    std::vector<myStruct> retval = extract_notworking(vec);

    print_vector(retval); // this line is only executed if extract_networking
                          // does not throw an exception
} catch (const domain_error& e) {
    // we can't access retval here so no worries
}

Вы можете получить доступ к retval, только если функция вернётся правильно (т.е. не выдает). В этом примере ваша функция будет выдавать, потому что vec пусто, поэтому print_vector никогда не будет вызываться.

Даже если вы сделаете это:

std::vector<myStruct> retval;

try {
    std::vector<myStruct> vec;

    retval = extract_notworking(vec);

    print_vector(retval);
} catch (const domain_error& e) {
    // we can access retval here but the assignment never happened
}

Поскольку функция не возвращала, присваивание ее возвращаемого значения retval не произошло, и retval по-прежнему является совершенно нормальной конструкцией по умолчанию vector, которую вы можете свободно использовать. Таким образом, в этом примере retval не назначено, а retval не напечатано, потому что extract_networking вызвало исключение, и выполнение перескочило в блок catch, прежде чем эти две вещи могли произойти.

4 голосов
/ 04 марта 2012

Когда вы throw исключение, вы не можете return, и наоборот. Вы можете думать об исключениях как об обобщенном return, предназначенном для исключительных обстоятельств и ошибок. Рассмотрим эту функцию:

int f(bool b) {
    if (b)
        return 42;
    throw std::runtime_error("Runtime error!");
}

Когда мы вызываем его, мы можем зафиксировать его нормальное возвращаемое значение (в данном случае int) в выражении, или мы можем захватить его исключительное возвращаемое значение (std::runtime_error) с использованием блока try с catch правильного типа:

try {

    int normal_result = f(b);

    // Use normal result.
    // (Exceptional result does not exist.)
    std::cout << normal_result << '\n';

} catch (const std::exception& exceptional_result) {

    // Use exceptional result.
    // (Normal result does not exist.)
    std::cout << exceptional_result.what() << '\n';

}

Сила исключений, конечно же, заключается в том, что они распространяются вверх по стеку вызовов, пока не достигнут соответствия catch. Таким образом, вы можете использовать их для выхода из глубоко вложенных вызовов функций и обеспечения правильного управления вашими ресурсами (памятью, файлами и т. Д.).

1 голос
/ 04 марта 2012

Что мне делать?Вернуть пустой вектор?Что произойдет, если я сгенерирую исключение для получателя возвращаемого значения?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...