I was listening to the latest CppChat, which was 2016-08-27:
It is of course useful if you have listened to the chat, but not a requirement. Part of the talk was about C++ move, more precise, about objects that have been moved from.
The talk was about some questions which I also had some time ago.
I think I found some good answers. They worked so far for me. These topics have not been mentioned in the chat, so maybe it will also help others if I share them here. And it is a nice possibility to blog something to an actual topic.
So here are my 2 cents…
The thing with moved from objects
I simplify one of the questions in the chat to the following:
What if someone wants to use a moved from object, shouldn’t there be a 'well defined' error?
What actually would ask for additional code in the implementation.
John said that no, because they are moved from, and, like a pointer which was deleted, using it will not make you happy at all.
This is of course correct.
And I could stop here, but….
A valid question that needs to be taken serious
I totally understand the question. I also asked it some time ago, when I started to learn about C++11 and move operations.
I have people around me that ask the same question. Some of them insists of additional check just because…
They do not discuss about using a deleted pointer, but what if someone uses a moved from object!
We need simple answers for this that bring it to the point. To keep things simple.
Not all people that could use modern C++ use it already because, among other things, such questions.
You know, embedded …. ?
A part of the problem
There is no discussion about what if we used a deleted pointer. I think a part of the explanation is that people have no chance to implement something on a pointer. So using a deleted pointer is not a discussion.
But a moved from object, you can hold it in your hands, see the methods, write code into the methods, smell the potential danger …
So you might start to think what if, …. and possible what to ensure that nobody uses this object after a move because, what if …
A simple solution (that is no solution)
My solution: do not use std::move anywhere other than in a constructor.
Of course this is not true, there might be single places where a std::move is a good idea,
But first, and in general, I think that those places are indeed very very rare, and second, this 'rule' is not for people that know what they do because they will not do it incorrect and therefor not use moved from objects.
This works for people that like and need coding rules.
If you can avoid to long discussions about the danger of modern C++ it is a good rule.
It is, for a generalized point of view, even the truth.
And if it helps to get
-std==c++11 or better in my cmake files, it is the best rule!
You know, embedded ….
When C++ discussions drift away
An other valid questions came up, why is a unique pointer not undefined after moving from it. If this does not create 2 classes of moved from objects, some that are somehow in a usable and others that are total unusable.
….and all of the sudden there was a discussion about type theory.
Sometimes we need the simple answer
After thinking about this it is easy to have an answer and keep things simple.
At least I think so, please correct me if I am wrong.
For me the simple answer is that the unique pointer is a nullptr after a move by accident. Because that’s how it is implemented.
A unique pointer could set some flag saying "I_was_moved_from' instead of setting it’s resource to nullptr.
It is not allowed to apply the deleter in the destructor if it was moved. So we need some information, remember, the destructor will be executed.
Using such a flag a unique pointer would, beside of being more inefficient and of bigger size, also behave undefined if you use it after move from it.
So unique pointer calls release on the moved from object it is constructed with or got assigned from.
There might be something to do
There is something to learn from unique pointer.
If you have a class that manages a resource it might have to do something in the destructor.
If this is the case, and moved from objects will be destructed, you need to know that you have no resource.
In case of the unique pointer this means setting it to a nullptr or make it equivalent to an unique pointer that points to nothing.
So the move operators, constructor and assignment, might set it on the source into something that makes still sense, like in case of the unique_ptr, or not.
Move may indeed require some thinking and action in the implementation
So, there is actually one possible additional invariant we need to check.
If we act on a resource in the destructor, we do need to check if the resource is not available anymore.
We can not free or release something that is used somewhere else because it was moved away from us.
If this is the case we very likely also need to implement our own move constructor and assingment operator instead of defaulting it.
My 2 cents
This is just an explanation from me for me, just as a programmer - as I would call me - sees this ;-)
I hope this will help to keep at least some discussions a little bit shorter
As usual, thanks for listening/reading!
If you have any comments, or want to report typos, please feel free to use the comment section below.