Why is there no ‘finally’ construct in C++?

Exception handling in C++ is limited to try/throw/catch. Unlike Object Pascal, Java, C# and Python, even in C++ 11, the finally construct has not been implemented.

I have seen an awful lot of C++ literature discussing “exception safe code”. Lippman writes that exception safe code is an important but advanced, difficult topic, beyond the scope of his Primer – which seems to imply that safe code is not fundamental to C++. Herb Sutter devotes 10 chapters to the topic in his Exceptional C++ !

Yet it seems to me that many of the problems encountered when attempting to write “exception safe code” could be quite well solved if the finally construct was implemented, allowing the programmer to ensure that even in the event of an exception, the program can be restored to a safe, stable, leak-free state, close to the point of allocation of resources and potentially problematic code. As a very experienced Delphi and C# programmer I use try.. finally blocks quite extensively in my code, as do most programmers in these languages.

Considering all the ‘bells and whistles’ implemented in C++ 11, I was astonished to find that ‘finally’ was still not there.

So, why has the finally construct never been implemented in C++? It’s really not a very difficult or advanced concept to grasp and goes a long ways towards helping the programmer to write ‘exception safe code’.

20

It’s really just a matter of understanding the philosophy and idioms of C++. Take your example of an operation that opens a database connection on a persistent class and has to make sure that it closes that connection if an exception is thrown. This is a matter of exception safety and applies to any language with exceptions (C++, C#, Delphi…).

In a language that uses try / finally, the code might look something like this:

database.Open();
try {
    database.DoRiskyOperation();
} finally {
    database.Close();
}

Simple and straightforward. There are, however, a few disadvantages:

  • If the language doesn’t have deterministic destructors, I always have to write the finally block, otherwise I leak resources.
  • If DoRiskyOperation is more than a single method call – if I have some processing to do in the try block – then the Close operation can end up being a decent bit away from the Open operation. I can’t write my cleanup right next to my acquisition.
  • If I have several resources that need to be acquired then freed in an exception-safe manner, I can end up with several layers deep of try / finally blocks.

The C++ approach would look like this:

ScopedDatabaseConnection scoped_connection(database);
database.DoRiskyOperation();

This completely solves all of the disadvantages of the finally approach. It has a couple of disadvantages of its own, but they’re relatively minor:

  • There’s a good chance you need to write the ScopedDatabaseConnection class yourself. However, it’s a very simple implementation – only 4 or 5 lines of code.
  • It involves creating an extra local variable – which you’re apparently not a fan of, based on your comment about “constantly creating and destroying classes to rely on their destructors to clean up your mess is very poor” – but a good compiler will optimize out any of the extra work that an extra local variable involves. Good C++ design relies a lot on these sorts of optimizations.

Personally, considering these advantages and disadvantages, I find RAII (Resource Acquisition Is Initialization) a much preferable technique to finally. Your mileage may vary.

Finally, because RAII is such a well-established idiom in C++, and to relieve developers of some of the burden of writing numerous Scoped... classes, there are libraries like ScopeGuard and Boost.ScopeExit that facilitate this sort of deterministic cleanup.

19

From Why doesn’t C++ provide a “finally” construct? in Bjarne Stroustrup’s C++ Style and Technique FAQ:

Because C++ supports an alternative that is almost always better: The “resource acquisition is initialization” technique (TC++PL3 section 14.4). The basic idea is to represent a resource by a local object, so that the local object’s destructor will release the resource. That way, the programmer cannot forget to release the resource.

27

The reason that C++ does not have finally is because it is not needed in C++.
finally is used to execute some code regardless of whether an exception has occurred or not, which almost always is some kind of cleanup code. In C++, this cleanup code should be in the destructor of the relevant class and the destructor will always be called, just like a finally block.
The idiom of using the destructor for your cleanup is called RAII.

Within the C++ community there might be more talk about ‘exception safe’ code, but it is almost equally important in other languages that have exceptions. The whole point of ‘exception safe’ code is that you think about in what state your code gets left if an exception occurs in any of the functions/methods that you call.
In C++, ‘exception safe’ code is slightly more important, because C++ does not have automatic garbage collection that takes care of objects that are left orphaned due to an exception.

The reason the exception safety is discussed more in the C++ community probably also stems from the fact that in C++ you have to be more aware of what can go wrong, because there are fewer default safety nets in the language.

17

Others have discussed RAII as the solution. It’s a perfectly good solution. But that doesn’t really address why they didn’t add finally as well since it’s a widely desired thing. The answer to that is more fundamental to the design and development of C++: throughout the development of C++ those involved have strongly resisted the introduction of design features that can be achieved using other features without a huge amount of fuss and especially where this requires the introduction of new keywords that could render older code incompatible. Since RAII provides a highly functional alternative to finally and you can actually roll your own finally in C++11 anyway, there was little call for it.

All you need to do is create a class Finally that calls the function passed to it’s constructor in it’s destructor. Then you can do this:

try
{
    Finally atEnd([&] () { database.close(); });

    database.doRisky();
}

Most native C++ programmers will, in general, prefer cleanly designed RAII objects however.

1

You can use a “trap” pattern – even if you don’t want to use try/catch block.

Put a simple object in the required scope. In this object’s destructor put your “finaly” logic. No matter what, when the stack is unwound, object’s destructor will be called and you’ll get your candy.

1

Well, you could sort of roll-your-own finally, using Lambdas, which would get the following to compile fine (using an example without RAII of course, not the nicest piece of code):

{
    FILE *file = fopen("test","w");

    finally close_the_file([&]{
        cout << "We're closing the file in a pseudo-finally clause." << endl;
        fclose(file);
    });
}

See this article.

I’m not sure I agree with assertions here that RAII is a superset of finally. The achilles heel of RAII is simple: exceptions. RAII is implemented with destructors, and it’s always wrong in C++ to throw out of a destructor. That means that you cannot use RAII when you need your cleanup code to throw. If finally were implemented, on the other hand, there’s no reason to believe that it would not be legal to throw from a finally block.

Consider a code path like this:

void foo() {
    try {
        ... stuff ...
        complex_cleanup();
    } catch (A& a) {
        handle_a(a);
        complex_cleanup();
        throw;
    } catch (B& b) {
        handle_b(b);
        complex_cleanup();
        throw;
    } catch (...) {
        handle_generic();
        complex_cleanup();
        throw;
    }
}

If we had finally we could write:

void foo() {
    try {
        ... stuff ...
    } catch (A& a) {
        handle_a(a);
        throw;
    } catch (B& b) {
        handle_b(b);
        throw;
    } catch (...) {
        handle_generic();
        throw;
    } finally {
        complex_cleanup();
    }
}

But there is no way, that I can find, to get the equivalent behavior using RAII.

If someone knows how to do this in C++, I’m very interested in the answer. I’d even be happy with something that relied on, for example, enforcing that all exceptions inherited from a single class with some special capabilities or something.

17

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật