Why vector access operators are not specified as noexcept?

前端 未结 3 1949
南笙
南笙 2020-12-05 02:05

Why std::vector\'s operator[], front and back member functions are not specified as noexcept?

3条回答
  •  天涯浪人
    2020-12-05 02:38

    As a complimentary to @SebastianRedl 's answer: why you will need noexcept?

    noexcept and std::vector

    As you might have known, a vector has its capacity. If it's full when push_back, it will allocate a bigger memory, copy(or move since C++11) all existing elements to the new trunk, and then add the new element to the back.

    Use copy constructor to expand a vector

    But what if an exception is thrown out while allocating memory, or copying the element to the new trunk?

    • If exception is thrown during allocating memory, the vector is in its original state. It's fine just re-throw the exception and let user handle it.

    • If exception is thrown during copy existing elements, all copied elements will be destroyed by calling destructor, allocated trunk will be freed, and exception thrown out to be handle by user code. (1)
      After destroy everything, the vector is back to the original state. Now it's safe to throw exception to let user handle it, without leaking any resource.

    noexcept and move

    Come to the era of C++ 11, we have a powerful weapon called move. It allows us to steal resources from unused objects. std::vector will use move when it needs to increase(or decrease) the capacity, as long as the move operation is noexcept.

    Suppose an exception throws during the move, the previous trunk is not the same as before move happens: resources are stolen, leaving the vector in an broken state. User cannot handle the exception because everything is in an nondeterministic state.

    Use move constructor to expand a vector

    That's why std::vector relies on move constructor to be noexcept.

    This is a demostration how client code would rely on noexcept as an interface specification. If later the noexcept requirement is not met, any code previously depends on it will be broken.


    Why not simply mark all function as noexcept?

    Short answer: exception safe code is hard to write.

    Long answer: noexcept set a strict limit to developer who implement the interface. If you want to remove the noexcept from an interface, the client code might be broken like the vector example given above; but if you want to make an interface noexcept, you are free to do it at any time.

    Thus, only when necessary, mark an interface as noexcept.


    In the Going Native 2013, Scott Meyers talked about above situation that without noexcept, the sanity of a program will fail.

    I also wrote a blog about it: https://xinhuang.github.io/posts/2013-12-31-when-to-use-noexcept-and-when-to-not.html

提交回复
热议问题