Resetting with move constructor - c++11

I was reading about the move constructor in an attempt to learn C++11 and it states that
The move constructor resets the source pointer rhs.data_. This way,
when the temporary is destroyed, delete[] will be harmlessly applied
to a null pointer.
Now the author does something like this
MemoryPage(MemoryPage&& other): size(0), buf(nullptr)
{
// pilfer other’s resource
size=other.size;
buf=other.buf;
// reset other
other.size=0;
other.buf=nullptr;
}
My question is if other.buf is actually a pointer isn't it suppose to be
delete other.buf;
why are we simply assigning nullptr to it during resetting ? Wont it end up to be a memory leak ?

My question is if other.buf is actually a pointer isn't it suppose to be
delete other.buf;
no, because a line earlier you copied the pointer to this->buf:
buf=other.buf;
move constructor is taking any memory buffers from other object, and is making sure other will safely be destroyed.
Here is nice description of what move constructor is actually doing:
Rvalue references, aka "move construction/assignment," are a useful
way to express that you’re constructing or assigning from an object
that will no longer be used for anything else — including, for
example, a temporary object — and so you can often get a decent
performance boost by simply stealing the guts of the other object
instead of making a potentially expensive deep copy.
http://herbsutter.com/2007/05/10/trip-report-april-2007-iso-c-standards-meeting/
so this line:
buf=other.buf;
is actually "stealing the guts of the other object." The other object no longer needs them, it will soon vanish.

Related

Advantage in writing two overloads for "T const&" and "T&&" rather than just the one taking a const ref (when we never want to move)?

Suppose I need to write a function which might take either a constant reference to an lvalue or a temporary value, is there any advantage in terms of performance in writing both overloads, the one taking a const T& and one taking T&&, if we do not want to move from the rvalue?
I was assuming having two overloads (or just writing the function once with universal references) would be beneficial but I can't pin down the exact reason. I even tried a small example: https://godbolt.org/z/53r34x4Mj but I can't really make sense of the generated code.
If you're never going to move from the argument under any circumstance, nor modify it, there is no benefit to writing the version that takes an r-value reference; the const type& version will accept r-values just fine (keeping them alive until the function returns) with no additional overhead.
The only reason to write both versions is if you plan to potentially modify or move-from the argument only when receiving an r-value reference, where the const reference case never does so, and doesn't copy either, because if it would need to copy anyway, you may as well just accept by value and get the best of all worlds (construct directly into argument for prvalues, move construct for xvalues, and copy for everything else, but without hand-writing the code to handle that).

What are the most common places that move semantics is used in C++11 STL?

I know that std::vector<T>::push_back() has move semantics support. So, when I add a named temporary instance to a vector, I can use std::move().
What are the other common places in the STL that I should grow the habit to add std::move()
I know that std::vector<T>::push_back() has move semantics support.
The support that push_back has is simply an additional overload that takes an rvalue reference, so that the new value T inside the vector can be constructed by invoking T(T&&) instead of T(const T&). The advantage is that the former can be implemented way more efficiently because it assumes that the passed rvalue reference is never going to be used afterwards.
Most Standard Library containers have added similar overloads to their push/enqueue/insert member functions. Additionally, the concept of emplacement has been added (e.g. std::vector<T>::emplace_back), where the values are constructed in place inside the container in order to avoid unnecessary temporaries. Emplacement should be preferred to insertion/pushing.
So, when I add a named temporary instance to a vector, I can use std::move().
"Named temporary" doesn't really make much sense. The idea is that you have an lvalue you don't care about anymore, and you want to turn it into a temporary by using std::move. Example:
Foo foo;
some_vector.emplace_back(std::move(foo));
// I'm sure `foo` won't be used from now on
Just remember that std::move is not special: it literally means static_cast<T&&>.
What are the other common places in the STL that I should grow the habit to add std::move?
This is a really broad question - you should add std::move everywhere it makes sense, not just in the context of the Standard Library. If you have a lvalue you know you're not going to use anymore in a particular code path, and you want to pass it/store it somewhere, then std::move it.

Why isn't std::move a keyword in C++?

Obviously, move semantics/r-value references were a much needed addition in C++11. One thing that has always bugged me though, is std::move. The purpose of std::move is to transform an l-value into an r-value. And yet, the compiler is perfectly happy to let you continue using that value as an l-value and you get to find out at runtime that you screwed up.
It seems like there is a missed opportunity to define move (or some other name) as a keyword (similar to *_cast) and actually have the compiler understand that the referenced value can no longer be used as an l-value here. I'm sure there is some implementation work to do this, but is there some fundamental reason why this wasn't done?
In C++, moved-from objects in are still objects. They can be used. They are usually in a defined state.
There are some optimizations you can do when you are willing to 'rip the guts' out of an object and use it elsewhere. The C++ committee decided these optimizations should be done implicitly and automatically in a few cases; usually where elision was already permitted, but where it wouldn't work for whatever reason.
Then, the ability to explicitly do this was added. Making this operation end the lifetime of its right hand side would complicate the lifetime rules of C++ to an extreme degree; rather than doing that, they noted they could be highly efficient without complicating the lifetime rules of C++ and leaving them exactly as-is.
It turns out there are a handful of flaws in this; to this extent, C++20 may be adding some "move and destroy the source" operations. In particular, a number of move-construction like operations are easier to write as nothrow if you can both move and destroy the source in one fell swoop.
Actually having it change the lifetime of automatic storage variables is not in the cards. Even describing how such a change would work, let alone making sure it doesn't break anything horribly, would be a challenge.
A simple example of why having it always happen wouldn't be good might be:
Foo foo;
if (some_condition) {
bar = std::move(foo);
}
the lifetime of foo is now a function of some_condition? You'd either have to ban the above with that kind of construct, or go down a pit of madness you may never get out of.

Indirect Member RAII: unique_ptr or optional?

Consider a class with a member that can't be stored directly, e.g., because it does not have a default constructor, and the enclosing class's constructor doesn't have enough information to create it:
class Foo
{
public:
Foo(){} // Default ctor
private:
/* Won't build: no default ctor or way to call it's
non-default ctor at Foo's ctor. */
Bar m_bar;
};
Clearly, m_bar needs to be stored differently, e.g., through a pointer. A std::unique_ptr seems better, though, as it will destruct it automatically:
std::unique_ptr<Bar> m_bar;
It's also possible to use std::experimental::optional, though:
std::experimenatl::optional<Bar> m_bar;
My questions are: 1. What are the tradeoffs? and 2. Does it make sense to build a class automating the choice between them?
Specifically, looking at the exception guarantees for the ctor of std::unique_ptr and the exception guarantees for the ctor of std::experimental::optional, it seems clear that the former must perform dynamic allocation and deallocation - runtime speed disadvantages, and the latter stores things in some (aligned) memory buffer - size disadvantages. Are these the only tradeoffs?
If these are indeed the tradeoffs, and given that both types share enough of their interface (ctor, operator*), does it make sense to automate the choice between them with something like
template<typename T>
using indirect_raii = typename std::conditional<
// 20 - arbitrary constant
sizeof(std::experimental::optional<T>) >
20 + sizeof(std::exerimental::optional<T>)sizeof(std::unique_ptr<T>),
std::unique_ptr<T>,
std::experimental::optional<T>>::type;
(Note: there is a question discussing the tradeoffs between these two as return types, but the question and answers focus on what each conveys to the callers of the function, which is irrelevant for these private members.)
IMO there are other trade-offs at play here:
unique_ptr is not copyable or copy-assignable, while optional is.
I suppose one thing you could do is make indirect_RAII a class-type and conditionally add definitions to make it copyable by calling Bar's copy ctor, even when unique_ptr is selected. (Or conversely, disable copying when it's an optional.)
optional types can have a constexpr constructor -- you can't really do the equivalent thing with a unique_ptr at compile-time.
Bar can be incomplete at the time that unique_ptr<Bar> is constructed. It cannot be incomplete at the time that optional<Bar> is known. In your example I guess you assume that Bar is complete since you take its size, but potentially you might want to implement a class using indirect_RAII where this isn't the case.
Even in cases where Bar is large, you still may find that e.g. std::vector<Foo> will perform better when optional is selected than when unique_ptr is. I would expect this to happen in cases where the vector is populated once, and then iterated over many times.
It may be that as a general rule of thumb, your size rule is good for common use in your program, but I guess for "common use" it doesn't really matter which one you pick. An alternative to using your indirect_RAII type is, just pick one or the other in each case, and in places where you would have taken advantage of the "generic interface", pass the type as a template parameter when necessary. And in performance-critical areas, make the appropriate choice manually.

C++ why is noexcept required in the context of Move Constructors and Move Assignment Operators to enable optimizations?

Consider the following class, with a move constructor and move assignment operator:
class my_class
{
protected:
double *my_data;
uint64_t my_data_length;
}
my_class(my_class&& other) noexcept : my_data_length{other.my_data_length}, my_data{other.my_data}
{
// Steal the data
other.my_data = nullptr;
other.my_data_length = 0;
}
const my_class& operator=(my_class&& other) noexcept
{
// Steal the data
std::swap(my_data_length, other.my_data_length);
std::swap(my_data, other.my_data);
return *this;
}
What is the purpose of noexcept here? I know that is hits to the compiler that no exceptions should be thrown by the following function, but how does this enable compiler optimizations?
The special importance of noexcept on move constructors and assignment operators is explained in detail in https://vimeo.com/channels/ndc2014/97337253
Basically, it doesn't enable "optimisations" in the traditional sense of allowing the compiler to generate better code. Instead it allows other types, such as containers in the library, to take a different code path when they can detect that moving the element types will never throw. That can enable taking an alternate code path that would not be safe if they could throw (e.g. because it would prevent the container from meeting exception-safety guarantees).
For example, when you do push_back(t) on a vector, if the vector is full (size() == capacity()) then it needs to allocate a new block of memory and copy all the existing elements into the new memory. If copying any of the elements throws an exception then the library just destroys all the elements it created in the new storage and deallocates the new memory, leaving the original vector is unchanged (thus meeting the strong exception-safety guarantee). It would be faster to move the existing elements to the new storage, but if moving could throw then any already-moved elements would have been altered already and meeting the strong guarantee would not be possible, so the library will only try to move them when it knows that can't throw, which it can only know if they are noexcept.
IMHO using noexcept will not enable any compiler optimization on its own. There are traits in STL:
std::is_nothrow_move_constructible
std::is_nothrow_move_assignable
STL containters like vector etc use these traits to test type T and use move constructors and assignment instead of copy constructors and assignment.
Why STL use these traits instead of:
std::is_move_constructible
std::is_move_assignable
Answer: to provide strong exception guarantee.
First of all I would remark that in move constructors or move assignment nothing should throw and there seems to be no need to this ever. The only thing which must be done in constructors/assignment operator is dealing with already allocated memory and pointers to them. Normally you should not call any other methods which can throw and your own moving inside your constructor/operator has no need to do so. But on the other hand a simple output of a debug message breaks this rule.
Optimization can be done in a some different ways. Automatically by the compiler and also by different implementations of code which uses your constructors and assignment operator. Take a look to the STL, there are some specializations for code which are different if you use exceptions or not which are implemented via type traits.
The compiler itself can optimize better while having the guarantee that any code did never throw. The compiler have a guaranteed call tree through your code which can be better inlined, compile time calculated or what so ever. The minimum optimization which can be done is to not store all the informations about the actual stack frame which is needed to handle the throw condition, like deallocation variables on the stack and other things.
There was also a question here: noexcept, stack unwinding and performance
Maybe your question is a duplicate to that?
A maybe helpful question related to this I found here: Are move constructors required to be noexcept?
This discuss the need of throwing in move operations.
What is the purpose of noexcept here?
At minimum saving some program space, which is not only relevant to move operations but for all functions. And if your class is used with STL containers or algorithms it can handled different which can result in better optimization if your STL implementation uses these informations. And maybe the compiler is able to get better general optimization because of a known call tree if all other things are compile time constant.

Resources