PSA: Add noexcept When Migrating to Visual C++ 2015

July 30, 2015

no comments

tl;dr — when migrating from Visual C++ 2013 to Visual C++ 2015, make sure that (1) your destructors do not throw exceptions, and (2) your move constructors are marked noexcept if they do not throw exceptions.

Less than a year ago, I described some of the reasons why noexcept is an important C++ language feature that lurks in the background and waits for the right moment to bite you in the neck.

Specifically, destructors and move constructors should ideally be marked as noexcept. For move constructors, this “ideally” means there are corner cases where performance won’t be optimal if you don’t mark the move constructor noexcept; for destructors, throwing destructors are a horrible idea. In fact, it turns out that using objects that have throwing destructors with Standard Library components (such as containers) leads to undefined behavior. Also, in C++ 11, destructors are implicitly marked noexcept without your intervention.

Why am I telling you all these things that you already know? Because if you’ve been using Visual C++ 2013, your compiler didn’t implement the noexcept keyword — which means you had no way of getting the correct, Standard behavior. Your Standard Library implementation couldn’t rely on move_if_noexcept, too.

When migrating to Visual C++ 2015, you need to verify two things.

First, verify that no exception can escape your destructors. In Visual C++ 2015, destructors are implicitly marked noexcept, and if an exception escapes from a destructor, your program is rudely aborted. Visual C++ has a nice warning if it can detect that your destructor throws an exception, but it (obviously) won’t detect every possible reason for throwing an exception.

main.cpp(37): warning C4297: 'person::~person': function assumed not to throw an exception but does
main.cpp(37): note: destructor or deallocator has a (possibly implicit) non-throwing exception specification

Second, verify that your move constructors are marked noexcept (assuming that they don’t throw exceptions). At the time of writing, std::vector in Visual C++ 2015 doesn’t care if your move constructor is noexcept, and will use it anyway — but that’s non-Standard behavior and subject to change.

And finally, if you have to maintain portability between Visual C++ 2013 and 2015, just use a macro, such as MYNOEXCEPT, that is conditionally defined to noexcept in Visual C++ 2015.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>