Are move constructors required to be noexcept? - c++

I've been reading some contradicting articles in regards whether move constructors/assignment is allowed to throw or not.
Therefore I'd like to ask whether move constructors/assignments are allowed to throw in the final C++11 standard?

Are move constructors in general allowed to throw? Yes. Should they? No.
In general, nothing you do within them should be anything that could throw. You shouldn't be allocating memory, calling other code, or anything like that. The only reason to write a move constructor is to abscond with someone else's memory pointers and object references. You should be copying a few basic types and nulling out the values in the other object. Those things shouldn't throw.
So while it is allowed, it's not a good idea. If you're doing it, rethink what you're doing in your move operations.

Here's to shed some further light on this.
It seems that std::vector in particular is picky about whether or not you declare your move constructors with noexcept. If you do, then std::vector will use them. If you don't then std::vector will resort to using your copy constructor instead. At least in some cases. Notably whenever it reshuffles items internally, after an internal array resize.
You can see the effects in this example, where noexcept is not declared:
http://coliru.stacked-crooked.com/a/285cd07a9a52da3b
And in this example, where it is:
http://coliru.stacked-crooked.com/a/d043774ec4c279ec
In the first example, std::vector uses the copy constructor already at the second and third insertion with push_back. In the second example, it does the same operation, but with the move constructor instead.

Related

Why does std::vector allow the use of a throwable move constructor for the type it contains?

Apparently, std::move_if_noexcept() will call the move constructor, even if it is not marked as noexcept if there is no copy constructor available.
From cpprefeerence.com (emphasis mine):
Notes
This is used, for example, by std::vector::resize, which may have to allocate new storage and then move or copy elements from old storage to new storage. If an exception occurs during this operation, std::vector::resize undoes everything it did to this point, which is only possible if std::move_if_noexcept was used to decide whether to use move construction or copy construction. (unless copy constructor is not available, in which case move constructor is used either way and the strong exception guarantee may be waived)
As std::vector is using this function on reallocation, that could leave the vector and possibly the application in an undetermined state. So, why would this be allowed?
Let's say you're doing what vector is doing when it would use move_if_noexcept. That is, you have some object obj, and you need to construct a new value of that type from obj. And after that, you're going to delete obj. That's a prime case for moving the object, so vector does that where possible.
If movement is noexcept, then moving obj is exception safe by definition. If it isn't noexcept, then you need to ask: what happens if the move constructor throws? What is the state of obj in that case? The answer is... you don't know. Even worse, what about the state from any objects you already moved from successfully? Can you move them back?
When it comes to copy constructors however, you do know. A copy constructor takes a const& to the source object. So by definition, a failed copy operation cannot modify obj (and yes, we know you can const_cast, but that makes your copy constructor a lie. Lies like that are why auto_ptr doesn't exist anymore, and I would guess that there's a blanket prohibition in the standard on lying copy constructors). So on a failed copy, obj is in its original state.
Therefore, if movement can throw, copying is preferred, as this provides the strong exception guarantee: in the event of an exception, everything goes back to the way it was.
However, if your only option is a throwing move, then you have two choices: make it so that such a type cannot ever be used with vector, or offer whatever exception guarantee the type itself offers on movement failure. And the latter is what is chosen.
It's allowed because that's what you asked for. Your choice of type doesn't allow for the strong exception guarantee, so it cannot be provided. But you can still make a vector of such types; you just need to deal with the possibility of non-copyable movement failure.
And since you're the kind of person who uses types that cannot provide a strong exception guarantee, you clearly must know how to handle these scenarios, right?

Why implementing swap() as non-throwing

I do understand why sometimes it is recommended to implement our own swap() function for a given class.
For instance, if we have a class following the pimpl idiom we would likely want to define our own copy constructor, so that it performs a deep copy of the contents of the object passed as an argument instead of the shallow copy that would be performed by the default copy constructor. The same could apply to the copy assignment operator.
Since it seems that std::swap() is implemented in terms of (at least, when it comes to C++03) both the copy constructor and the copy assignment operator. It would be inefficient to perform deep copies of the objects to be swapped, since just a swap of the pointers contained by these objects need to be done.
My question is why we should implement our swap() function as a non-throwing one.
In the case explained above, I assume it is just about semantics: since no new resources are being allocated (i.e.: two existing pointers are just being swapped). It wouldn't make much sense for such a kind of function to throw an exception.
However, there may be other reasons or scenarios I am overlooking in this reasoning.
My question is why we should implement our swap() function as a non-throwing one
Because swap is completely useless if it might throw.
Consider: you swap two instances, and the operation throws. Now, what state are they in?
The strong guarantee is that there are no side-effects if an exception was thrown, meaning both original objects are left in their original state.
If we can't meet the strong guarantee, we simply can't use swap in many cases, because there's no way to recover usefully from a failure, and there's no point in writing that version of swap at all.
Because there's no reason for it to throw.
The trivial implementation of swap (now) uses move-assignment and -construction.
There's generally no reason for a move-constructor to throw: it doesn't allocate anything new, it's just re-seating existing data. There's generally no reason for move-assignment to throw (as above), and destructors should never throw - and those are the only operations required.
EDIT
I've originally understood the question as "why would you use the throw specifier on the swap function. This answer might be off topic since I doesn't explain why would swap never throw.
I think the best answer is why not ?.
Why would you not specify that a function will never throw when this function as no reason to throw ?
You should always implement function as non-throwing when they have no reason to throw exception: you offer stronger guaranty for your function.
Furthermore, with some meta programming, you can take advantages of functions being non-throwing. Some STL classes use that to have faster member function when the swap/copy/move(C++11) is no-throw. (Actually I'm not sure that they take advantage of a function being no-throw in pre-C++11 code)
For some classes such as
a class following the pimpl idiom
we know that the implementation of swap will not need to throw because
It wouldn't make much sense for such a kind of function to throw an exception.
When it doesn't make sense to throw an exception, then it is best not to throw an exception.
There can be other classes such as those that contain complex members without a specialized swap function, but with potentially throwing copy constructor / assignment. For such classes we can not implement swap that never throws.
swaping your pImpls can't fail, in a well-formed program. (And the behaviour in an ill formed program doesn't matter). There is nothing to throw

Implementing move assignment in terms of destructor and move constructor

Say I have a class which manages memory and thus needs user-defined special member functions (imagine vector or similar).
Consider the following implementation of the move-assignment operator:
Class& operator=(Class&& rhs)
{
this->~Class(); // call destructor
new (this) Class(std::move(rhs)); // call move constructor in-place
}
Is it valid to implement a move-assignment operator this way? That is, does calling a destructor and constructor in this way not run afoul of any object lifetime rules in the language?
Is it a good idea to implement a move-assignment operator this way? If not, why not, and is there a better canonical way?
It's not valid: What if this move assignment is called as part of moving a child object? Then you destroy the child (assuming it has a virtual destructor) and recreate in its place a parent object.
I would say that even in a non-virtual context it's still a bad idea because you don't see the syntax very often and it may make the code harder to grok for future maintainers.
The best approach is to avoid having to write your own move constructor entirely (and using the default) by having all your class members take care of moving themselves. For example rely on unique_ptr, etc. Failing that it seems that implementing it in terms of swap (as the copy-and-swap for copy assignment) would be an easily understandable mechanism.
It may be valid(1). To address your specific issue about dtor/ctor lifetimes, yes that is valid(2). That is how the original implementation for vector worked.
It may be a good idea (it probably isn't), but you may not want a canonical way.(3)
(1) There is controversy about whether or moves need to be valid in the self-move case.
Arguing for self-move safety is the position that code should be safe (duh), we certainly expect self assignment to be safe. Also some user experience reports that for many algorithms which use move, self-move is possible and tedious to check for.
Arguing against self-move safety is the position that the whole point of move semantics is time savings and for that reason moves should be as fast as possible. A self-move check can be expensive relative to the cost of a move. Note that the compiler will never generate self-move code, because natural (not casted) rvalues can't be self-moved. The only way to have a self-move is if a "std::move()" cast is explicitly invoked. This puts the burden on the caller of std::move() to either verify that self-move isn't involved or convince themselves that it isn't. Note also that it would be trivial to create a user defined equivalent of "std::move" that checked for self-move and then did nothing. If you don't support self-move, you might want to document that.
(2) This is not a template so you can know if the expression "new (this) Class(std::move(rhs));" can throw. If it can, then no, this isn't valid.
(3) This code may be a puzzle to maintainers, who might expect a more traditional swap approach, but there is a potential drawbacks to the swap approach. If the resources being released by the target need to be released as soon as possible (such as a mutex), then swap has the drawback that the resources are swapped into the move source object. If the move is the result of a call to "std::move()" the move source object may not be immediately disposed of. (Since this isn't a template you can know what resources are being freed. If memory is the only resource being freed, then this isn't an issue.)
A better approach might be to factor out the resource freeing code from the destructor and the resource moving code from the move constructor and then just call those (inlined) routines in this move assignment operator.

Can queue::pop return a value now?

I know std::queue::pop() returns void. For two reasons:
exception safety: something might throw after removing the element
to be able to return the value by reference
Fine.
Now if I understand the new C++11 move semantics correctly, the second is no longer a valid argument.
So... the only thing preventing std::queue to have a pop-like function returning the value lies in the possibility that the move constructor throws?
I have a hard time thinking of situations where such a move constructor would throw. Who knows of an example?
I guess the same goes for std::stack::pop(), std::vector::pop_front(), std::vector::pop_back(), std::deque::pop_front(), std::deque::pop_back(), std::list::pop_front(), std::list::pop_back() and what not.
There aren't many cases where std::move() can throw in the standard library but there are cases. For example, if the container uses a stateful allocator, its children also use this allocator, but it won't be moved to a result: this would rather get a default constructed version of an allocator (if I remove correctly). Given that the allocators are stateful this means that the object can't be moved and thus the move construction fails with an exception. Why does this type then have a move constructor? Well, because it might be instantiated with non-stateful allocator in which case moving won't throw. In addition, once we move to user defined classes we have no idea under which condition moving them might throw.
Using clever SFINAE techniques it would indeed be possible to have an atomic non-throwing pop_and_move() for just datatypes that implement no-throwing move or no-throwing copy.
There is even a noexcept() construct available to see if something might throw.
One of the new concepts in C++11 in particular that extends SFINAE is that if the body doesn't compile the function doesn't exist. Thus one could implement based on noexcept().
I would say for backward compatibility the function would need a new name, which therefore allows it to co-exist with the existing functionality of calling them separately, not breaking containers of types that do not have the semantics to allow it.
Another problem is, that not every class really benefits from moving, i.e., they might only have a copy ctor.
struct DontLikeMoves{
// some data, whatever...
DontLikeMoves(DontLikeMoves const& other){
// might throw, who knows!
// and this will even get called for rvalues
}
};

Under what conditions should I be thinking about implementing a move constructor and a move operator?

For standard copy constructors and assignment operators, I always think about implementing them or deleteing the defaults out of existence, if my class implements a destructor.
For the new move constructor and move operator, what is the right way to think about whether or not an implementation is necessary?
As a first pass of transitioning a system from pre-C++0x, could I just delete the default move constructor and move operator or should I leave them alone?
You don't have to worry about it, in the sense that when you user-declare a destructor (or anything else listed in 12.8/9), that blocks the default move constructor from being generated. So there's not the same risk as there is with copies, that the default is wrong.
So, as the first pass leave them alone. There may be places in your existing code where C++11 move semantics allow a move, whereas C++03 dictates a copy. Your class will continue to be copied, and if that caused no performance problems in C++03 then I can't immediately think of any reason why it would in C++11. If it did cause performance problems in C++03, then you have an opportunity to fix a bug in your code that you never got around to before, but that's an opportunity, not an obligation ;-)
If you later implement move construction and assignment, they will be moved, and in particular you'll want to do this if you think that C++11 clients of your class are less likely to use "swaptimization" to avoid copies, more likely to pass your type by value, etc, than C++03 clients were.
When writing new classes in C++11, you need to consider and implement move under the same criteria that you considered and implemented swap in C++03. A class that can be copied implements the C++11 concept of "movable", (much as a class that can be copied in C++03 can be swapped via the default implementation in std), because "movable" doesn't say what state the source is left in - in particular it's permitted to be unchanged. So a copy is valid as a move, it's just not necessarily an efficient one, and for many classes you'll find that unlike a "good" move or swap, a copy can throw.
You might find that you have to implement move for your classes in cases where you have a destructor (hence no default move constructor), and you also have a data member which is movable but not copyable (hence no default copy constructor either). That's when move becomes important semantically as well as for performance.
With C++11, you very rarely need to provide a destructor or copy semantics, due to the way the library is written. Compiler provided members pretty much always do fine (provided they are implemented correctly: MSVC forces you to implement a lot of move semantics by hand, which is very bothersome).
In case you have to implement a custom destructor, use the following approach:
Implement a move constructor, and an assignment operator taking by value (using copy&swap: note that you cannot use std::swap since it uses the assignment. You have to provide a private swap yourself). Pay attention to exception guarantees (look up std::move_if_noexcept).
If necessary, implement a copy constructor. Otherwise, delete it. Beware that non default copy semantics rarely make sense.
Also, a virtual destructor counts as a custom destructor: provide or delete copy + move semantics when declaring a virtual destructor.
Since they are used as an optimization you should implement them if the optimization is applicable to your class. If you can "steal" the internal resource your class is holding from a temporary object that is about to be destroyed. std::vector is a perfect example, where move constructor only assigns pointers to internal buffer leaving the temporary object empty (effectively stealing the elements).