Evgenij LegotskojAug. 6, 2018, 2:52 a.m.

The idiom RAII and the principle of structured programming that a function must have one entry point and one exit point


The world of programming in C ++ in the new standards allows us to get up a variety of things, thanks to which we can safely abandon some old statements or principles, or simply flexibly approach these principles.

I would like to outline my view on the work of the RAII idiom and the C ++ 11 standard with respect to one established principle whose authorship is attributed to Edsger Dijkstra :

"The module (in this case the function) must have only one entry point and only one exit point"

For this principle, multiple returns in a function / method are contrary to the principles of structured programming for the following reasons:

  • the complexity of debugging code with the use of multiple returns returns increases with the number of these same return, that is, you never know when the function or method of an object just exited.
    the complexity of code support, when all the points of the call are not visible at the initial look at the function. Also, it is not known whether the code added to the end of the function will execute or not, especially if the program logic should always execute this code. That is, in the case of multiple returns, you will have to implement this code before every call to the return operator.

But modern C ++ has already changed significantly since the times of Dijkstra and the means of the latest C ++ standards allow to bypass or significantly level out the influence of the reasons that caused the formulation of the principles of structured programming.

One of these tools in C++ can be the RAII idiom, lambda function , and std::function from the standard library.

RAII (Resource Acquisition Is Initialization) - the program idiom of object-oriented programming, the meaning of which is that with the help of certain software mechanisms the obtaining of a certain resource is inseparably combined with initialization, and the release is with the destruction of the object.

Thus, thanks to RAII and lambda functions, we can get around some problems with multiple return, in particular with the fact that some code should always be called at the end of the function, regardless of the rest of the function code logic. But this is closer to the end of the article.

And now let's look at the pros and cons of using multiple return.

The first reason is that the complexity of debugging the program code increases with multiple return. But at the same time, already in 2018, modern debuggers allow you to define using breakpoints where the function came from, and the presence of multiple returns also allows you to significantly reduce the nesting of the code when using the if else constructs. Thus, we can get a more compact program code, which only will benefit from an understanding of what the function does, despite the presence of multiple return.

Consider the example

There are two functions that are called in another main function and the algorithm of the main function is constructed from the result of the work of those first two functions.

bool exampleFunction_1();
bool exampleFunction_2();

The main function, written according to the principles of structured programming

int examlpeFunctionMain()
    int result = 0;

    if (exampleFunction_1())
        result = 1;
    else if (exampleFunction_2())
        result = 2;

    return result;

If there were more such functions then the nesting of the if else constructs could increase significantly, which would not benefit the program code.

Therefore, we rewrite this code to use multiple return.

int examlpeFunctionMain()
    if (exampleFunction_1()) return 1;
    if (exampleFunction_2()) return 2;
    return 0;

The code has become much more compact and obvious, which is much clearer. That is, the use of multiple exit points from a function may allow the code to be improved on the contrary, rather than complicate it.

And now we give arguments that one exit point will be better if it is required that a certain program code at the end of the function is always called, and if you use several exit points, you need to duplicate this code and add it before all exit points. For example, this code can be the logging of the result of the function.

Let us consider an example of such an argument.

int examlpeFunctionMain()
    int result = 0;

    if (exampleFunction_1())
        result = 1;
    else if (exampleFunction_2())
        result = 2;

    std::cout << "Logging result " << result << std::endl;
    return result;

At the end of the above function, there is some code that emulates the logging. Then, if there are several breakpoints, this code will have to be duplicated, and our previous beautiful variant will become such ugly.

int examlpeFunctionMain()
    if (exampleFunction_1())
        std::cout << "Logging result " << 1 << std::endl;
        return 1;

    if (exampleFunction_2())
        std::cout << "Logging result " << 2 << std::endl;
        return 2;

    std::cout << "Logging result " << 0 << std::endl;
    return 0;

As you can see here, not only is the number of rows increased by one, so there was also the possibility of making a mistake when copying, if you forget to change the digit in the output of the log.

Such an argument for the presence of only one exit point from the function becomes quite reasonable.

But now I suggest that we turn to the modern possibilities of the C ++ programming language.

The idiom RAII implies that when you destroy an object in the destructor, you can free up memory, and also execute some program code. Such code can be the execution of a logging code. But we do not have any such objects? Yes, at the moment, no, but I suggest writing a class for using such an object.

This will be a sample ScopExit class. Let us consider it below.


#include <functional>

class ScopeExit
    template<typename T>
    explicit inline ScopeExit(T&& onScopeExitFunction) :

    inline ~ScopeExit()

    std::function<void()> m_onScopeExitFunction;

#endif // SCOPEEXIT_H

The class has a private field std::function , this field will be responsible for storing the method we need, which will execute the code at the end of the function.

In the class constructor, this field is initialized by the passed template argument, which can be a functor or a lambda function.

In the class destructor, this function is called. That is, when the object is destroyed, a function will be called, which we place in the object of this class when it is created.

Using this class, you can rewrite the above code as follows:

int examlpeFunctionMain()
    int result = 0;
    ScopeExit scopeExit([&result](){ std::cout << "Logging result " << result << std::endl; });

    if (exampleFunction_1()) return (result = 1);
    if (exampleFunction_2()) return (result = 2);
    return 0;

The meaning of this code is that there is a variable result, which will store the code with which the function will end.

Next, a class object is created for ScopeExit, which at the end of the method will be destroyed and will cause the lambda in the destructor.

This lambda is passed as an argument to the constructor of the ScopeExit class. In this case, the lambda grabs the variable result to get the actual function completion code.

Further checks are performed and the function ends at one of the three exit points, returning the value of the function completion code. What is important, the lambda function will be executed regardless of where the function ended. This means that the logging is guaranteed to be fulfilled, regardless of whether they forgot to register it or not.


This example is artificial and you can also forget to assign the value of the variable result, but if you just need to execute some program code, regardless of where the function ended, then this option is quite suitable. So, the statement that some code may not be executed at the end of the function also loses its foundation.

In general, adhere to the established principles of development - it's good, but they came up with it many years ago, and the development tools stepped forward already. Therefore, you just need to study your programming language well and think with your head. Since many development problems that were 20 years ago can now be elegantly solved using the programming language.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate


Only authorized users can post comments.
Please, Log in or Sign up

Let me recommend you a great European Fornex hosting.

Fornex has proven itself to be a stable host over the years.

For Django projects I recommend VPS hosting

Following the link you will receive a 5% discount on shared hosting services, dedicated servers, VPS and VPN

View Hosting

C++ - Test 001. The first program and data types

  • Result:66points,
  • Rating points-1
  • korsar
  • Nov. 23, 2022, 9:57 a.m.

C++ - Test 005. Structures and Classes

  • Result:50points,
  • Rating points-4

C++ - Тест 003. Условия и циклы

  • Result:78points,
  • Rating points2
Last comments

GameDev on Qt - Tutorial 5. The explosion of bullets using sprite images

Если вдруг кто-то прочитает.... Скачал проект, скомпилил, запустил. Всё красиво и объектно ориентировано, но вот FPS дико страдает, когда появляется 10+ врагов. Может есть какие-то надстрой…
  • juvf
  • Nov. 25, 2022, 1:14 a.m.

Qt/C++ - Lesson 051. QMediaPlayer – simple audio player

Добрый день. Подскажите, как можно перехватить в Qt или Qml уровень воспроизводимого звука? Т.е. требуется сделать виртуальный винтажный индикатор (стрелочный или светодиодный), который бы …
  • juvf
  • Nov. 3, 2022, 4:20 a.m.

QML - Lesson 007. ListView. Dynamic creation and deletion of elements

Добрый день. Очень полезная статья. Спасибо. Вопрос такой: 1) нужно "взять" кнопку 2 пальцем (прикаснулись пальцем к кнопке 2, держим, через 2-3 кнопка оторвалась от ListView) и пере…

PyQt5 - Lesson 007. Works with QML QtQuick (Signals and slots)

А можно ли из QML сделать привязку свойства к свойству пайтоновского объекта? Ну, т.е. , например, у нашего объекта Calculator обхвялем свойства sumresult и subresult c с декоратором @pyqtProp…

Python Image Recognition with TensorFlow and Keras

А что собственно выводит программа, как вывести то что она смогла распознать?
Now discuss on the forum

Sorting the added QML elements in the ListModel

I am writing an alarm clock in QML, I am required to sort the alarms in ascending order (depending on the date or time (if there are several alarms on the same day). I've done the sorting …

Как добавить в скрипт размер каждого файла в Мб ?

IDLE (Python 3.10 64-bit) Win 10 Есть такой скрипт: Поиск перечня файлов в папке и запись списка: import ospath = 'E:\Мой Python\__Видеокурсы Python'rez = sorted(os.listdir(pa…
  • nkly
  • Oct. 18, 2022, 10:14 a.m.

Как сохранить данные древовидной модели на основе QStandardItemModel в файл

Вы меня неправильно поняли. Допустим я собираю кулинарные рецепты и один из них - рецепт супа Харчо. Структура файла данных такова: { node:Рецепт супа Харчо parent:Вкусные блюда, …

Вопрос по Qt Creator

Добрый день. Не знаю, подобную проблему я не решал.

Задать другой класс div-у

Добрый день. Попробуйте использовать Selenium. Это библиотека есть в виде Python модуля и она позволяет загружать страницу и манипулировать html элементами. Как я понимаю, в ней можно…
© EVILEG 2015-2022
Recommend hosting TIMEWEB