Move which throws?

As far as I understand, move-constructors and move-assign should be marked with noexcept so that the compiler uses them, for example, when redistributing inside a vector.

However, is there any real case where the move-assign, move-construct function can actually be generated?

Update:

Classes that, for example, have a dedicated resource when it is constructed cannot be moved.

+6
source share
2 answers

However, is there any real case where redirecting, move-construct (or swap) can actually throw away?

Yes. Consider the implementation of std::list . The end iterator must indicate "one minus the last item" in the list. There are implementations of std::list , where what end points to is a dynamically allocated node. Even the default constructor allocates such a node, so when you call end() , there is something to indicate.

In such an implementation, each constructor must allocate a node for end() to indicate ... even a move constructor. This distribution may fail and throw an exception.

The same behavior can apply to any container node.

There are also implementations of these node-based containers that perform short-string optimization: they embed the end of the node inside the container class itself instead of dynamically highlighting it. Thus, the default constructor (and the move constructor) should not highlight anything.

The forwarding assignment operator can throw for any container<X> if propagate_on_container_move_assignment::value is false for the container allocator, and if the allocator in lhs is not equal to the allocator in rhs. In this case, the transition assignment operator is not allowed to transfer memory ownership from rhs to lhs. This cannot be the case if you use std::allocator , since all instances of std::allocator are equal to each other.

Update

Here is an example of the correspondence and portability of the case where propagate_on_container_move_assignment::value is false. It has been tested against the latest version of VS, gcc and clang.

 #include <cassert> #include <cstddef> #include <iostream> #include <vector> template <class T> class allocator { int id_; public: using value_type = T; allocator(int id) noexcept : id_(id) {} template <class U> allocator(allocator<U> const& u) noexcept : id_(u.id_) {} value_type* allocate(std::size_t n) { return static_cast<value_type*>(::operator new (n*sizeof(value_type))); } void deallocate(value_type* p, std::size_t) noexcept { ::operator delete(p); } template <class U, class V> friend bool operator==(allocator<U> const& x, allocator<V> const& y) noexcept { return x.id_ == y.id_; } }; template <class T, class U> bool operator!=(allocator<T> const& x, allocator<U> const& y) noexcept { return !(x == y); } template <class T> using vector = std::vector<T, allocator<T>>; struct A { static bool time_to_throw; A() = default; A(const A&) {if (time_to_throw) throw 1;} A& operator=(const A&) {if (time_to_throw) throw 1; return *this;} }; bool A::time_to_throw = false; int main() { vector<A> v1(5, A{}, allocator<A>{1}); vector<A> v2(allocator<A>{2}); v2 = std::move(v1); try { A::time_to_throw = true; v1 = std::move(v2); assert(false); } catch (int i) { std::cout << i << '\n'; } } 

This program displays:

 1 

which indicates that the motion assignment operator vector<T, A> is copying / moving its elements when propagate_on_container_move_assignment::value is false and the two allocators in question are not compared equal. If any of these copies / movements is thrown, then the job of moving the container throws.

+7
source

Yes, propellant movement constructors exist in the wild. Consider std::pair<T, U> , where T intransitively movable and U is only copyable (suppose that copies can be thrown away). Then you have a useful std::pair<T, U> move constructor that can be thrown.

There is a utility std::move_if_noexcept in the standard library that you need (it is useful to implement std::vector::resize with at least a basic exception guarantee).

See also Move Constructors and Strong Exception Guarantee.

+4
source

Source: https://habr.com/ru/post/957569/


All Articles