According to cppreference, std::copyable is defined as follows:
template <class T>
concept copyable =
std::copy_constructible<T> &&
std::movable<T> && // <-- !!
std::assignable_from<T&, T&> &&
std::assignable_from<T&, const T&> &&
std::assignable_from<T&, const T>;
I'm wondering why a copyable object should be also movable. Just think about a global variable that is accessed by several functions. While it makes sense to copy that variable (for example to save its state before calling another function) it makes no sense, and actually would be very bad, to move it since other functions might not know that that variable is currently in an unspecified state. So why exactly does std::copyable subsume std::movable ?
This comes from two facts. Firstly, even if you don't define move constructor + move assignment you can still construct/assign object from r-value reference if you define copying functions. Just take a look at the example:
#include <utility>
struct foo {
foo() = default;
foo(const foo&) = default;
foo& operator=(const foo&) = default;
};
int main()
{
foo f;
foo b = std::move(f);
}
Secondly (and maybe more importantly), the copyable type can always be (or according to standard now must be) also movable in some way. If object is copyable then worst case scenario for move is just copying internal data.
Note that since I declared copy constructor the compiler DID NOT generate default move constructor.
While it makes sense to copy that variable (for example to save its state before calling another function) it makes no sense, and actually would be very bad, to move it since other functions might not know that that variable is currently in an unspecified state.
There's a strong, unstated presumption here of what moving actually means that is probably the source of confusion. Consider the type:
class Person {
std::string name;
public:
Person(std::string);
Person(Person const& rhs) : name(rhs.name) { }
Person& operator=(Person const& rhs) { name = rhs.name; return *this; }
};
What does moving a Person do? Well, an rvalue of type Person can bind to Person const&... and that'd be the only candidate... so moving would invoke the copy constructor. Moving does a copy! This isn't a rare occurrence either - moving doesn't have to be destructive or more efficient than copying, it just can be.
Broadly speaking, there are four sane categories of types:
Types for which move and copy do the same thing (e.g. int)
Types for which move can be an optimization of copy that consumes resources (e.g. string or vector<int>)
Types which can be moved but not copied (e.g. unique_ptr<int>)
Types which can be neither moved nor copied (e.g. mutex)
There are a lot of types that fall into group 1 there. And the kind of variable mentioned in OP should also fall into group 1.
Notably missing from this list is a type that is copyable but not movable, since that makes very little sense from an operational stand-point. If you can copy the type, and you don't want destructive behavior on moving, just make moving also copy the type.
As such, you can view these groups as a kind of hierarchy. (3) expands on (4), and (1) and (2) expand on (3) - you can't really differentiate (1) from (2) syntactically. Hence, copyable subsumes movable.
Related
Let's look at some trivially move-constructible and (not trivially) copy-constructible (but still copy-constructible) user-defined (class) type A:
struct A
{
A() = default;
A(A const &) {}
A(A &&) = default;
};
Then moving of A (move-construction or move-assignment) literally perfroms the following: a source bitwise copied to a destination, despite of operation's name "moving". During trivial moving right hand side is (formally) not const, but triviality of the whole operation requires (actual) non-mutability of right hand side, isn't it? On my mind it means, that trivial copy-operation and trivial move-operation are exactly the same in their deep nature (in terms of memory, memory-layout, bits etc). Am I right?
If it is so, then I think, if I see trivially move-constructible, but not trivially copy-constructible type in user code, then I evidently see some antipattern. Am I right?
Is there an example of such artificial but usable type, which is not trivially copy-constructible/assignable, but trivially move-constructible/assignable?
Is there a use case where a type could have a trivial copy constructor without having a trivial move constructor? Sure.
For example, it could be useful to have a pointer wrapper type that will always be empty when moved from. There's no reason for the copy constructor to be non-trivial, but the move constructor would have to set the old value to NULL.
template<typename T>
class empty_on_move
{
T *ptr_;
public:
empty_on_move(const empty_on_move&) = default;
empty_on_move(empty_on_move &&other) : ptr_(other.ptr_) {other.ptr_ = nullptr;}
...
};
empty_on_move doesn't own the object, which is why it's OK to have multiple copies of it. It exists solely to make sure that when you move from it, the pointer is in a well-understood state. As such, is_trivially_copy_constructible<empty_on_move<T>> is true, while is_trivially_move_constructible<empty_on_move<T>> is false.
It would mainly be for use inside of other classes which want to give pointers that particular behavior. That way, you don't have to explicitly write code into their move constructors/assignments to NULL those fields out.
That being said, you're really asking the wrong question. Why? Because the answer doesn't matter.
The only time that the triviality of a copy/move constructor/assignment matters is when you need the type to be Trivially Copyable. It is that property which permits the use of memcpy and such things, not the trivially of the individual operations. The trivially copyable property requires that the copy/move constructor/assignment and destructors all are trivial (in C++14, the requirement is that they can be trivial or deleted, but at least one must be non-deleted).
If you're writing a wrapper around some type (or writing a sum/product type), and you want to expose the properties of that type, you only need concern yourself with exposing Trivial Copyability. That is, if T (or Ts...) is trivially copyable, then your type should be trivially copyable too.
But otherwise, you shouldn't feel the need to have a trivial copy constructor just because T does.
In Scott Meyers' "Effective Modern C++", he writes:
It's worth nothing that because std::mutex is a move-only type (i.e., a type that can be
moved, but not copied), a side effect of adding m to Polynomial is that Polynomial loses the ability to be copied. It can still be moved, however.
Here, he adds a std::mutex m as a member variable to a class Polynomial in the context of explaining why one should protect access to const member variable of a class(while multi-threading). I understood the concept he explained. but one thing which I need to have some more explanation is "why Adding a move only type to a class makes that class as move only type not copy-able"?, why types like std::mutex and std::atomic is move only type by default? how can we get over with it if we want to perform copy operation even when adding move only type of variable to our class?
"why Adding a move only type to a class makes that class as move only type not copy-able"
This is not entierly true. adding non copyable member variable prevents you from writing something like Type (const Type& t) = default; , but you can still implement you own copy constructor which ignores the non copyable member
class Type{
int integer;
std::mutex m;
public:
Type() = default;
Type(const Type& rhs): integer (rhs.integer){}
}
Other than this, you can find numerous examples of objects that contain move-only members, but they are themselves non movable, simply because the developer deleted the move constructor.
why types like std::mutex and std::atomic is move only type by default?
Neither of them implement move constructor. this is a wrong statement.
std::mutex is not copyable only because the standard says so. They could probably have written a std::mutex that was copyable, but they decided not to.
As a guess, a non-copyable std::mutex might be more efficient, safer, or easier to understand.
As an example, here is why it might be safer/easier to understand: What does it mean to copy a std::mutex that is locked? I, personally, have no idea what the right answer is; I suspect that the right answer is "that is nonsense". There is no "answer of least surprise".
Instead of having a surprising answer in concurrency code, by blocking copy we avoid the question. People storing a mutex who want to copy have to decide themselves what they want it to do.
C++ will under some circumstances automatically generate a copy constructor. Under more circumstances it will let you do MyClass(MyClass const&)=default and write one when you ask for it.
If your class contains a non-copyable class, it won't generate one, and you cannot ask for it. This is because the generated copy constructor basically copies its members; if you cannot copy a member, it cannot generate a copy constructor.
So mutex cannot be copied because the standard says so.
If a struct or class contains a non-copyable member, the default copy constructor cannot be used. You have to write one yourself explicitly.
If your type needs to store a mutex, one approach to prevent the headache of having to maintain a copy ctor that manually copies all of its other members is to stick your non-mutex state into a sub-struct, and then use its default copy. Then you decide what to do with the mutex during the copy, and your copy ctor (and assignment copy operator) remain simple.
struct bob_with_mutex {
sturct bob_simple_data {
int x, y, z;
std::vector<char> buff;
};
bob_simple_data data;
std::mutex m;
bob_with_mutex( bob_with_mutex const& o ):
data(o.data)
{}
bob_with_mutex& operator=( bob_with_mutex const& o )
{
data = o.data;
return *this;
}
};
the type bob has a mixture of a mutex and some data. The data is stored in a sub-structure. The copy ctor of bob_with_mutex cannot be defaulted, but it simply says "copy the data, and nothing else".
The copy of the bob has its own mutex.
One possibility is to change the mutex type to a pointer to a mutex. You can copy the pointer, but there will still only be one copy of the mutex. You may want to use a smart pointer.
When implementing move constructors and move assignment operators, one often writes code like this:
p = other.p;
other.p = 0;
The implicitly defined move operations would be implemented with code like this:
p = std::move(other.p);
Which would be wrong, because moving a pointer variable does not set it to null. Why is that? Are there any cases were we would like the move operations to leave the original pointer variable unchanged?
Note: By "moving", I do not just mean the subexpression std::move(other.p), I mean the whole expression p = std::move(other.p). So, why is there no special language rule that says "If the right hand side of an assignment is a pointer xvalue, it is set to null after the assignment has taken place."?
Setting a raw pointer to null after moving it implies that the pointer represents ownership. However, lots of pointers are used to represent relationships. Moreover, for a long time it is recommended that ownership relations are represented differently than using a raw pointer. For example, the ownership relation you are referring to is represented by std::unique_ptr<T>. If you want the implicitly generated move operations take care of your ownership all you need to do is to use members which actually represent (and implement) the desired ownership behavior.
Also, the behavior of the generated move operations is consistent with what was done with the copy operations: they also don't make any ownership assumptions and don't do e.g. a deep copy if a pointer is copied. If you want this to happen you also need to create a suitable class encoding the relevant semantics.
Moving renders the moved-from object "invalid". It does not automatically set it to a safe "empty" state. In accordance with C++'s long-standing principle of "don't pay for what you don't use", that's your job if you want it.
I think the answer is : implementing such a behavior yourself is pretty much trivial and hence the Standard didn't feel any need to impose any rule on the compiler itself. The C++ language is huge and not everything can be imagined before its use. Take for example, C++'s template. It was not first designed to be used the way it is used today (i.e it's metaprogramming capability). So I think, the Standard just gives the freedom, and didn't make any specific rule for std::move(other.p), following one of it's the design-principle: "You don't pay for what you don't use".
Although, std::unique_ptr is movable, though not copyable. So if you want pointer-semantic which is movable and copyable both, then here is one trivial implementation:
template<typename T>
struct movable_ptr
{
T *pointer;
movable_ptr(T *ptr=0) : pointer(ptr) {}
movable_ptr<T>& operator=(T *ptr) { pointer = ptr; return *this; }
movable_ptr(movable_ptr<T> && other)
{
pointer = other.pointer;
other.pointer = 0;
}
movable_ptr<T>& operator=(movable_ptr<T> && other)
{
pointer = other.pointer;
other.pointer = 0;
return *this;
}
T* operator->() const { return pointer; }
T& operator*() const { return *pointer; }
movable_ptr(movable_ptr<T> const & other) = default;
movable_ptr<T> & operator=(movable_ptr<T> const & other) = default;
};
Now you can write classes, without writing your own move-semantics:
struct T
{
movable_ptr<A> aptr;
movable_ptr<B> bptr;
//...
//and now you could simply say
T(T&&) = default;
T& operator=(T&&) = default;
};
Note that you still have to write copy-semantics and the destructor, as movable_ptr is not smart pointer.
For example, if you have a pointer to a shared object. Remember, that after moving an object must remain in an internally consistent state, so setting a pointer that must not be null to a null value is not correct.
I.e.:
struct foo
{
bar* shared_factory; // This can be the same for several 'foo's
// and must never null.
};
Edit
Here is a quote about MoveConstructibe from the standard:
T u = rv;
...
rv’s state is unspecified [ Note:rv must still meet the requirements
of the library component that is using it. The operations listed in
those requirements must work as specified whether rv has been moved
from or not.
I think what makes the difference here is a fully blown object on the one hand and a POD on the other hand.
For objects either the implementer specifies what move construction and move assignment should do or the compiler generates a default. The default is to call the move constructors/assignment operators of all member.
For POD's (and a pointer is a POD) C++ inherits from C and nothing is done with it when not explicitely coded. It's just the same behavior as POD members in a class are treated in a constructor. If you don't explicitely put them in the initializer list, well, then they stay uninitialized and are a source of potential bugs. AFAIK this is even valid for compiler generated constructors! That's why I took on the habit of generally initializing all members to be on the safe side.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can someone please explain move semantics to me?
Could someone point me to a good source or explain it here what are the move semantics?
Forget about C++0x for the moment. Move semantics are something that is language independent -- C++0x merely provides a standard way to perform operations with move semantics.
Definition
Move semantics define the behaviour of certain operations. Most of the time they are contrasted with copy semantics, so it would be useful to define them first.
Assignment with copy semantics has the following behaviour:
// Copy semantics
assert(b == c);
a = b;
assert(a == b && b == c);
i.e. a ends up equal to b, and we leave b unchanged.
Assignment with move semantics has weaker post conditions:
// Move semantics
assert(b == c);
move(a, b); // not C++0x
assert(a == c);
Note that there is no longer any guarantee that b remains unchanged after the assignment with move semantics. This is the crucial difference.
Uses
One benefit of move semantics is that it allows optimisations in certain situations. Consider the following regular value type:
struct A { T* x; };
Assume also that we define two objects of type A to be equal iff their x member point to equal values.
bool operator==(const A& lhs, const A& rhs) { return *lhs.x == *rhs.x; }
Finally assume that we define an object A to have sole ownership over the pointee of their x member.
A::~A() { delete x; }
A::A(const A& rhs) : x(new T(rhs.x)) {}
A& A::operator=(const A& rhs) { if (this != &rhs) *x = *rhs.x; }
Now suppose we want to define a function to swap two A objects.
We could do it the normal way with copy semantics.
void swap(A& a, A& b)
{
A t = a;
a = b;
b = t;
}
However, this is unnecessarily inefficient. What are we doing?
We create a copy of a into t.
We then copy b into a.
Then copy t into b.
Finally, destroy t.
If T objects are expensive to copy then this is wasteful. If I asked you to swap two files on your computer, you wouldn't create a third file then copy and paste the file contents around before destroying your temporary file, would you? No, you'd move one file away, move the second into the first position, then finally move the first file back into the second. No need to copy data.
In our case, it's easy to move around objects of type A:
// Not C++0x
void move(A& lhs, A& rhs)
{
lhs.x = rhs.x;
rhs.x = nullptr;
}
We simply move rhs's pointer into lhs and then relinquish rhs ownership of that pointer (by setting it to null). This should illuminate why the weaker post condition of move semantics allows optimisations.
With this new move operation defined, we can define an optimised swap:
void swap(A& a, A& b)
{
A t;
move(t, a);
move(a, b);
move(b, t);
}
Another advantage of move semantics is that it allows you to move around objects that are unable to be copied. A prime example of this is std::auto_ptr.
C++0x
C++0x allows move semantics through its rvalue reference feature. Specifically, operations of the kind:
a = b;
Have move semantics when b is an rvalue reference (spelt T&&), otherwise they have copy semantics. You can force move semantics by using the std::move function (different from the move I defined earlier) when b is not an rvalue reference:
a = std::move(b);
std::move is a simple function that essentially casts its argument to an rvalue reference. Note that the results of expressions (such as a function call) are automatically rvalue references, so you can exploit move semantics in those cases without changing your code.
To define move optimisations, you need to define a move constructor and move assignment operator:
T::T(T&&);
T& operator=(T&&);
As these operations have move semantics, you are free to modify the arguments passed in (provided you leave the object in a destructible state).
Conclusion
That's essentially all there is to it. Note that rvalue references are also used to allow perfect forwarding in C++0x (due to the specifically crafted type system interactions between rvalue references and other types), but this isn't really related to move semantics, so I haven't discussed it here.
Basically, rvalue references allow you to detect when objects are temporaries and you don't have to preserve their internal state. This allows for much more efficient code where C++03 used to have to copy all the time, in C++0x you can keep re-using the same resources. In addition, rvalue references enable perfect forwarding.
Have a look at this answer.
I read a ton of text explanations for about a year and didn't grasp everything about r-value references until I watch this excellent presentation by Scott Meyer : http://skillsmatter.com/podcast/home/move-semanticsperfect-forwarding-and-rvalue-references
He explain in a way that is funny and slow enough to understand each thing that happens in the processes.
I know, it 1h30 but really, it's the best explanation I've had in the last year.
After having read the articles (like the other answers), watching this video did melt it together in my mind in a consistent way and few days after I was able to explain it to some colleagues and explain how to use std::unique_ptr (as it is related - it only allow move semantics, not copy) because it requires understanding of std::move(), that requires understanding move semantics.
glad to see such a question and I'm happy to share my point. I think you are asking about a bug-fix on the designation of the C++ language itself, not just another C++ language feature. The "bug" has been there for tens of year. That is, the copy constructor.
Copy constructors seems very strange if you know in physics there are lots of things that can not be copied like energy and mass. That's just a joke, but in fact in the world of programming too, objects like exclusive file descriptors are not copyable. So C++ programmers and designers invented some tricks to deal with that. There are 3 famous: NRVO, boost::noncopyable and std::auto_ptr.
NRVO (Named Return Value Optimization) is a technic that lets a function returns an object by value without calling the copy constructor. But the problem with NRVO is that though the copy constructor is not actually called, a public copy constructor declaration is still needed, which means, objects of boost::noncopyable is not compatible with NRVO.
std::auto_ptr is another trial to bypass the copy constructor. You might have seen its "copy constructor" implemented like
template <typename _T>
auto_ptr(auto_ptr<_T>& source)
{
_ptr = source._ptr; // where _ptr is the pointer to the contained object
source._ptr = NULL;
}
This is not a copy at all, but a "move". You could consider this kind of behavior as the prototype of a move semantic.
But std::auto_ptr also has its own problem: it is not compatible with STL containers. So, unfortunately, anything about noncopyable is painful.
That was painful until, the C++0x move semantic is finally published and implemented by the compiler makers.
In simple way, you could just think of move semantic as something same as the "copy" behavior of std::auto_ptr, but with a full support by the language features so it works fine with containers and algorithm.
By the way in C++0x the std::auto_ptr is deprecated and a new template type std::unique_ptr is recommended.
My story will end now. Please refer to other posts if you want to know more about it like strange syntax and rvalue system.
Consider a class of which copies need to be made. The vast majority of the data elements in the copy must strictly reflect the original, however there are select few elements whose state is not to be preserved and need to be reinitialized.
Is it bad form to call a default assignment operator from the copy constructor?
The default assignment operator will behave well with Plain Old Data( int,double,char,short) as well user defined classes per their assignment operators. Pointers would need to be treated separately.
One drawback is that this method renders the assignment operator crippled since the extra reinitialization is not performed. It is also not possible to disable the use of the assignment operator thus opening up the option of the user to create a broken class by using the incomplete default assignment operator A obj1,obj2; obj2=obj1; /* Could result is an incorrectly initialized obj2 */ .
It would be good to relax the requirement that to a(orig.a),b(orig.b)... in addition to a(0),b(0) ... must be written. Needing to write all of the initialization twice creates two places for errors and if new variables (say double x,y,z) were to be added to the class, initialization code would need to correctly added in at least 2 places instead of 1.
Is there a better way?
Is there be a better way in C++0x?
class A {
public:
A(): a(0),b(0),c(0),d(0)
A(const A & orig){
*this = orig; /* <----- is this "bad"? */
c = int();
}
public:
int a,b,c,d;
};
A X;
X.a = 123;
X.b = 456;
X.c = 789;
X.d = 987;
A Y(X);
printf("X: %d %d %d %d\n",X.a,X.b,X.c,X.d);
printf("Y: %d %d %d %d\n",Y.a,Y.b,Y.c,Y.d);
Output:
X: 123 456 789 987
Y: 123 456 0 987
Alternative Copy Constructor:
A(const A & orig):a(orig.a),b(orig.b),c(0),d(orig.d){} /* <-- is this "better"? */
As brone points out, you're better off implementing assignment in terms of copy construction. I prefer an alternative idiom to his:
T& T::operator=(T t) {
swap(*this, t);
return *this;
}
It's a bit shorter, and can take advantage of some esoteric language features to improve performance. Like any good piece of C++ code, it also has some subtleties to watch for.
First, the t parameter is intentionally passed by value, so that the copy constructor will be called (most of the time) and we can modify is to our heart's content without affecting the original value. Using const T& would fail to compile, and T& would trigger some surprising behaviour by modifying the assigned-from value.
This technique also requires swap to be specialized for the type in a way that doesn't use the type's assignment operator (as std::swap does), or it will cause an infinite recursion. Be careful of any stray using std::swap or using namespace std, as they will pull std::swap into scope and cause problems if you didn't specialize swap for T. Overload resolution and ADL will ensure the correct version of swap is used if you have defined it.
There are a couple of ways to define swap for a type. The first method uses a swap member function to do the actual work and has a swap specialization that delegates to it, like so:
class T {
public:
// ....
void swap(T&) { ... }
};
void swap(T& a, T& b) { a.swap(b); }
This is pretty common in the standard library; std::vector, for example, has swapping implemented this way. If you have a swap member function you can just call it directly from the assignment operator and avoid any issues with function lookup.
Another way is to declare swap as a friend function and have it do all of the work:
class T {
// ....
friend void swap(T& a, T& b);
};
void swap(T& a, T& b) { ... }
I prefer the second one, as swap() usually isn't an integral part of the class' interface; it seems more appropriate as a free function. It's a matter of taste, however.
Having an optimized swap for a type is a common method of achieving some of the benefits of rvalue references in C++0x, so it's a good idea in general if the class can take advantage of it and you really need the performance.
With your version of the copy constructor the members are first default-constructed and then assigned.
With integral types this doesn't matter, but if you had non-trivial members like std::strings this is unneccessary overhead.
Thus, yes, in general your alternative copy constructor is better, but if you only have integral types as members it doesn't really matter.
Essentially, what you are saying is that you have some members of your class which don't contribute to the identity of the class. As it currently stands you have this expressed by using the assignment operator to copy class members and then resetting those members which shouldn't be copied. This leaves you with an assignment operator that is inconsistent with the copy constructor.
Much better would be to use the copy and swap idiom, and express which members shouldn't be copied in the copy constructor. You still have one place where the "don't copy this member" behaviour is expressed, but now your assignment operator and copy constructor are consistent.
class A
{
public:
A() : a(), b(), c(), d() {}
A(const A& other)
: a(other.a)
, b(other.b)
, c() // c isn't copied!
, d(other.d)
A& operator=(const A& other)
{
A tmp(other); // doesn't copy other.c
swap(tmp);
return *this;
}
void Swap(A& other)
{
using std::swap;
swap(a, other.a);
swap(b, other.b);
swap(c, other.c); // see note
swap(d, other.d);
}
private:
// ...
};
Note: in the swap member function, I have swapped the c member. For the purposes of use in the assignment operator this preserves the behaviour to match that of the copy constructor: it re-initializes the c member. If you leave the swap function public, or provide access to it through a swap free function you should make sure that this behaviour is suitable for other uses of swap.
Personally I think the broken assignment operator is killer. I always say that people should read the documentation and not do anything it tells them not to, but even so it's just too easy to write an assignment without thinking about it, or use a template which requires the type to be assignable. There's a reason for the noncopyable idiom: if operator= isn't going to work, it's just too dangerous to leave it accessible.
If I remember rightly, C++0x will let you do this:
private:
A &operator=(const A &) = default;
Then at least it's only the class itself which can use the broken default assignment operator, and you'd hope that in this restricted context it's easier to be careful.
I would call it bad form, not because you double-assign all your objects, but because in my experience it's often bad form to rely on the default copy constructor / assignment operator for a specific set of functionality. Since these are not in the source anywhere, it's hard to tell that the behavior you want depends on their behavior. For instance, what if someone in a year wants to add a vector of strings to your class? You no longer have the plain old datatypes, and it would be very hard for a maintainer to know that they were breaking things.
I think that, nice as DRY is, creating subtle un-specified requirements is much worse from a maintenance point of view. Even repeating yourself, as bad as that is, is less evil.
I think the better way is not to implement a copy constructor if the behaviour is trivial (in your case it appears to be broken: at least assignment and copying should have similar semantics but your code suggests this won't be so - but then I suppose it is a contrived example). Code that is generated for you cannot be wrong.
If you need to implement those methods, most likely the class could do with a fast swap method and thus be able to reuse the copy constructor to implement the assignment operator.
If you for some reason need to provide a default shallow copy constructor, then C++0X has
X(const X&) = default;
But I don't think there is an idiom for weird semantics. In this case using assignment instead of initialization is cheap (since leaving ints uninitialized doesn't cost anything), so you might just as well do it like this.