为何std::deque可移动构造但不具备nothrow特性?
std::deque's move constructor noexcept despite efficient state swapping? Great question—this is one of those cases where the surface-level efficiency of swap makes the lack of noexcept on move construction feel counterintuitive. Let’s break down the key reasons:
Internal structure differences from
std::vector
Unlikestd::vector, which uses a single contiguous buffer (so moving just transfers three pointers with zero allocation),std::dequeis built from a collection of smaller, non-contiguous "nodes" managed via a dynamic "map" (an array of pointers to these nodes). While many implementations will transfer ownership of this map directly during move construction, the C++ standard doesn’t mandate this behavior. Some implementations might include edge cases where move construction requires allocating memory—for example, if the source deque uses a stack-allocated tiny map (a small-object optimization), moving to a new deque could trigger a heap allocation for the map, which can throwstd::bad_alloc.The standard doesn’t require
noexceptfordeque’s move constructor
The C++ standard explicitly marksstd::vector’s move constructor asnoexceptbecause its internal structure guarantees no allocations or risky operations during moves. Forstd::deque, though, the standard leaves exception specifications up to the implementation. This flexibility lets library designers prioritize other optimizations (like memory efficiency for small deques) even if it means move construction can’t be strictlynoexcept.Move construction ≠ swap
You’re right thatstd::deque::swapisnoexcept—it just swaps internal pointers between two existing objects, no allocations or construction steps involved. Move construction, on the other hand, is about creating a new object that takes over the source’s resources. Even when most of the work is just transferring pointers, the act of initializing the new deque’s members (like setting up sentinel values or default-initializing auxiliary state) could, in some edge cases, introduce operations that might throw—something the standard can’t rule out across all implementations.
In short: while std::deque can efficiently transfer state, the complexity of its internal design and the standard’s flexibility for implementations mean move construction can’t be guaranteed to never throw, hence the absence of noexcept.
内容的提问来源于stack exchange,提问作者Brett Hale

