Why in the example code below, object is copied twice? According documentation constructor of thread class copies all arguments to thread-local storage so we have reason for the first copy. What about second?
class A {
public:
A() {cout << "[C]" << endl;}
~A() {cout << "[~D]" << endl;}
A(A const& src) {cout << "[COPY]" << endl;}
A& operator=(A const& src) {cout << "[=}" << endl; return *this;}
void operator() () {cout << "#" << endl;}
};
void foo()
{
A a;
thread t{a};
t.join();
}
Output from above:
[C]
[COPY]
[COPY]
[~D]
#
[~D]
[~D]
Edit:
Well yes, after adding move constructor:
A(A && src) {cout << "[MOVE]" << endl;}
The output is like this:
[C]
[COPY]
[MOVE]
[~D]
#
[~D]
[~D]
For anything you want to move or avoid copies, prefer move constructors and std::move.
But Why doesn't this happen automatically for me?
Move in C++ is conservative. It generally will only move if you explicitly write std::move(). This was done because move semantics, if extended beyond very explicit circumstances, might break older code. Automatic-moves are often restricted to very careful set of circumstances for this reason.
In order to avoid copies in this situation, you need to shift a around by using std::move(a) (even when passing it into std::thread). The reason it makes a copy the first time around is because std::thread can't guarantee that the value will exist after you have finished constructing the std::thread (and you haven't explicitly moved it in). Thusly, it will do the safe thing and make a copy (not take a reference/pointer to what you passed in and store it: the code has no idea whether or not you'll keep it alive or not).
Having both a move constructor and using std::move will allow the compiler to maximally and efficiently move your structure. If you're using VC++ (with the CTP or not), you must explicitly write the move constructor, otherwise MSVC will (even sometimes erroneously) declare and use a Copy constructor.
The object is copied twice because the object cannot be moved. The standard does not require this, but it is legitimate behavior.
What's happening inside of the implementation is that it seems to be doing a decay_copy of the parameters, as required by the standard. But it doesn't do the decay_copy into the final destination; it does it into some internal, possibly stack, storage. Then it moves the objects from that temporary storage to the final location within the thread. Since your type is not moveable, it must perform a copy.
If you make your type moveable, you'll find that the second copy becomes a move.
Why might an implementation do this, rather than just copying directly into the final destination? There could be any number of implementation-dependent reasons. It may have just been simpler to build a tuple of the function+parameters on the stack, then move that into the eventual destination.
try with: thread t{std::move(a)};
Related
Can someone please explain me one thing. From the one side the move constructor was designed to optimize the memory & processor usage by eliminating unnecessary copying an objects BUT from other side almost everywhere the move constructor is going to be used the compiler uses copy elision, disabling the usage of the move ctor? Isn't it irrational?
There are plenty of cases where the move constructor will still get called and copy elision is not being used:
// inserting existing objects into a container
MyObject myobject;
std::vector<MyObject> myvector;
myvector.push_back(std::move(myobject));
// inserting temporary objects into a container
myvector.push_back(MyObject());
// swapping
MyObject other;
std::swap(myobject, other);
// calling functions with existing objects
void foo(MyObject x);
foo(std::move(myobject));
... and many more.
The only instance where there is mandatory copy elision (since C++17) is when constructing values from the result of a function call or a constructor. In such cases, the compiler isn't even allowed to use the move constructor. For example:
MyObject bar() {
return MyObject();
}
void example() {
MyObject x = bar(); // copy elision here
MyObject y = MyObject(); // also here
}
In general, the purpose of copy elision is not to eliminate move construction alltogether, but to avoid unnecessary constructions when initializing variables from prvalues.
See cppreference on Copy Elision.
Here is a simple example where move is called. It is a toy example for which the rule of zero could have been relevant, but assume that there are also other members inside the class that require going with the rule of five.
class A {
std::string s;
public:
A(const char* s = ""): s(s) {}
~A() {}
A(const A& a): s(a.s) {
std::cout << "copy ctor" << std::endl;
}
A& operator=(const A& a) {
s = a.s;
std::cout << "copy assignment" << std::endl;
return *this;
}
A(A&& a): s(std::move(a.s)) {
std::cout << "move ctor" << std::endl;
}
A& operator=(A&& a) {
s = std::move(a.s);
std::cout << "move assignment" << std::endl;
return *this;
}
};
int main() {
A a;
a = "hi"; // move
// suppose we KNOW here that a is not needed anymore
A a2 = std::move(a); // move
a = "bye"; // move
}
Code: http://coliru.stacked-crooked.com/a/97d25c43e0edb00b
Because copy elision has limits, compiler must know the lifetime of an object to predict whether copy elision can be done.
For example:
std::vecter<MyObj> v;
v.push(MyObj()); // compiler has a higher chance to do the copy elision
but consider this:
MyObj my_obj;
v.push(my_obj)
// ...
// my_obj will never use
in this case, the compiler won't know that the my_obj will be never use, so the normal copy will performed. If efficiency matters, you have to use v.push(std::move(my_obj)); to explicit tell the compiler that "I will never use my_obj again"
move constructor was designed to optimize the memory & processor usage by eliminating unnecessary copying an object
That is not true. A move construction creates a new object to which the data of the old object is "moved" (in the worst case if all data of the source object is fully enclosed in it, it is as expensive as a regular copy) a move constructor has only benefited over a copy constructor if you have member variables that can be swapped like pointers or containers that support swapping (or if it holds resources that can't be copied)
So copy elision is always desired over a move ctor. But that does not mean that a move ctor does not have any use. In many cases, however, a move ctor is just syntactic sugar over swap and reset/empty/destruct (not exactly true, but closely).
Besides the swap case, a move ctor is also useful for things that are or should not be copyable and for which you don't want to use pointers. e.g. a std::uniqu_ptr should not be copyable because of the unique ownership, but you might want to pass the ownership while calling a function, so moving its resources is important.
You can see move sematic as a standardized process, so that copy elision if possible, and if it is not a fallback to move ctor.
Why in the example code below, object is copied twice? According documentation constructor of thread class copies all arguments to thread-local storage so we have reason for the first copy. What about second?
class A {
public:
A() {cout << "[C]" << endl;}
~A() {cout << "[~D]" << endl;}
A(A const& src) {cout << "[COPY]" << endl;}
A& operator=(A const& src) {cout << "[=}" << endl; return *this;}
void operator() () {cout << "#" << endl;}
};
void foo()
{
A a;
thread t{a};
t.join();
}
Output from above:
[C]
[COPY]
[COPY]
[~D]
#
[~D]
[~D]
Edit:
Well yes, after adding move constructor:
A(A && src) {cout << "[MOVE]" << endl;}
The output is like this:
[C]
[COPY]
[MOVE]
[~D]
#
[~D]
[~D]
For anything you want to move or avoid copies, prefer move constructors and std::move.
But Why doesn't this happen automatically for me?
Move in C++ is conservative. It generally will only move if you explicitly write std::move(). This was done because move semantics, if extended beyond very explicit circumstances, might break older code. Automatic-moves are often restricted to very careful set of circumstances for this reason.
In order to avoid copies in this situation, you need to shift a around by using std::move(a) (even when passing it into std::thread). The reason it makes a copy the first time around is because std::thread can't guarantee that the value will exist after you have finished constructing the std::thread (and you haven't explicitly moved it in). Thusly, it will do the safe thing and make a copy (not take a reference/pointer to what you passed in and store it: the code has no idea whether or not you'll keep it alive or not).
Having both a move constructor and using std::move will allow the compiler to maximally and efficiently move your structure. If you're using VC++ (with the CTP or not), you must explicitly write the move constructor, otherwise MSVC will (even sometimes erroneously) declare and use a Copy constructor.
The object is copied twice because the object cannot be moved. The standard does not require this, but it is legitimate behavior.
What's happening inside of the implementation is that it seems to be doing a decay_copy of the parameters, as required by the standard. But it doesn't do the decay_copy into the final destination; it does it into some internal, possibly stack, storage. Then it moves the objects from that temporary storage to the final location within the thread. Since your type is not moveable, it must perform a copy.
If you make your type moveable, you'll find that the second copy becomes a move.
Why might an implementation do this, rather than just copying directly into the final destination? There could be any number of implementation-dependent reasons. It may have just been simpler to build a tuple of the function+parameters on the stack, then move that into the eventual destination.
try with: thread t{std::move(a)};
Consider the below code, where a composing class with another class as its member is being instantiated:
class CopyAble {
private:
int mem1;
public:
CopyAble(int n1) : mem1(n1) {
cout << "Inside the CopyAble constructor" << endl;
}
CopyAble(const CopyAble& obj) {
cout << "Inside the CopyAble copy constructor" << endl;
this->mem1 = obj.mem1;
return *this;
}
CopyAble& operator=(const CopyAble& obj) {
cout << "Inside the CopyAble assignment constructor" << endl;
this->mem1 = obj.mem1;
}
~CopyAble() {};
};
class CopyAbleComposer {
private:
CopyAble memObj;
public:
CopyAbleComposer(CopyAble m1) : memObj(m1) {
cout << "Composing the composer" << endl;
}
~CopyAbleComposer() {}
};
int main()
{
CopyAble ca(10);
CopyAbleComposer cac(ca);
return 0;
}
When I run this, I get the output:
Inside the CopyAble constructor
Inside the CopyAble copy constructor
Inside the CopyAble copy constructor
Composing the composer
Which means that the CopyAble copy constructor is being run twice - once when the CopyAble object is passed into the CopyAbleComposer constructor, and again when the initializer memObj(m1) runs.
Is this an idiomatic use of the copy constructor? It seems very inefficient that the copy constructor runs twice when we try to initialize a member object with a passed-in object of the same type, and it seems like a trap a lot of C++ programmers can easily fall into without realizing it.
EDIT: I don't think this is a duplicate of the question regarding passing a reference into the copy constructor. Here, we are being forced to pass a reference into a regular constructor to avoid duplicate object creation, my question was that is this generally known that class constructors in C++ should have objects passed in by reference to avoid this kind of duplicate copy?
You should accept CopyAble by reference at CopyAbleComposer(CopyAble m1), otherwise a copy constructor will be called to construct an argument. You should also mark it as explicit to avoid accidental invocations:
explicit CopyAbleComposer(const CopyAble & m1)
Pass-by-value and the associated copying is a pretty widely known property of C++. Actually, in the past C++ was criticized for this gratuitious copying, which happened silently, was hard to avoid and could lead to decreased performance. This is humorously mentioned e.g. here:
You accidentally create a dozen instances of yourself and shoot them all in the foot. Providing emergency medical assistance is impossible since you can't tell which are bitwise copies and which are just pointing at others and saying, "That's me, over there."
C++98
When any function/method is declared to receive an argument by value, this sort of copying happens. It doesn't matter if it's a constructor, a "stand-alone" function or a method. To avoid this, use a const reference:
CopyAbleComposer(const CopyAble& m1) : memObj(m1)
{
...
}
Note: even if you rearrange your code as below, one copy always remains. This has been a major deficiency in C++ for a long time.
CopyAbleComposer cac(CopyAble(10)); // initializing mem1 by a temporary object
C++11
C++11 introduced move semantics, which replaces the additional copy by a "move" operation, which is supposed to be more efficient than copy: in the common case where an object allocates memory dynamically, "move" only reassigns some pointers, while "copy" allocates and deallocates memory.
To benefit from optimization offered by move semantics, you should undo the "optimization" you maybe did for C++98, and pass arguments by value. In addition, when initializing the mem1 member, you should invoke the move constructor:
CopyAbleComposer(CopyAble m1) : memObj(std::move(m1)) {
cout << "Composing the composer" << endl;
}
Finally, you should implement the move constructor:
CopyAble(CopyAble&& obj) {
cout << "Inside the CopyAble move constructor" << endl;
this->mem1 = obj.mem1;
}
Then you should see that the "copy" message doesn't appear, and is replaced by the "move" message.
See this question for more details.
Note: In all these examples, the CopyAble objects are assumed to be much more complex, with copy and move constructors doing non-trivial work (typically, resource management). In modern C++, resource management is considered a separate concern, in the context of separation of concerns. That is, any class that needs a non-default copy or move constructor, should be as small as possible. This is also called the Rule of Zero.
I've heard that you should always prefer "pass by value" in C++11 because of the introduction of move semantics. I wanted to see what the hype was all about and constructed a test case. First my class:
struct MyClass {
MyClass() { }
MyClass(const MyClass&) { std::cout << "Copy construct" << std::endl; }
MyClass(MyClass&&) { std::cout << "Move construct" << std::endl; }
~MyClass() { }
};
And the test harness:
class Test
{
public:
void pass_by_lvalue_ref(const MyClass& myClass)
{
_MyClass.push_back(myClass);
}
void pass_by_rvalue_ref(MyClass&& myClass)
{
_MyClass.push_back(std::move(myClass));
}
void pass_by_value(MyClass myClass)
{
_MyClass.push_back(std::move(myClass));
}
private:
std::vector<MyClass> _MyClass;
};
Presumably, pass_by_value should outperform pass_by_lvalue_ref and pass_by_rvalue_ref (together, not separately).
int main()
{
MyClass myClass;
Test Test;
std::cout << "--lvalue_ref--\n";
Test.pass_by_lvalue_ref(myClass);
std::cout << "--rvalue_ref--\n";
Test.pass_by_rvalue_ref(MyClass{});
std::cout << "--value - lvalue--\n";
Test.pass_by_value(myClass);
std::cout << "--value - rvalue--\n";
Test.pass_by_value(MyClass{});
}
This is my output on GCC 4.9.2 with -O2:
--lvalue_ref--
Copy construct
--rvalue_ref--
Move construct
Copy construct
--value - lvalue--
Copy construct
Move construct
Copy construct
Copy construct
--value - rvalue--
Move construct
As you can see, the non-pass_by_value functions requires a total of 2 copy constructs and 1 move construct. The pass_by_value function requires a total of 3 copy constructs and 2 move constructs. It looks like that, as expected, the object is going to be copied anyway, so why does everyone say pass by value?
First, your reporting is entirely flawed. Each of your functions pushes back to the same vector. When that vector runs out of capacity (which depends upon how many items you've inserted so far), it is going to trigger a re-allocation which will require more moves and/or copies than an insertion which doesn't trigger an allocation.
Second, std::vector::push_back has a strong exception safety guarantee. So if your move constructor is not noexcept, it will not use it (unless the class is non-copyable). It will use the copy constructor instead.
Third,
I've heard that you should always prefer "pass by value" in C++11
because of the introduction of move semantics.
I'm pretty sure you didn't hear that from any reputable source. Or are actually inappropriately paraphrasing what was actually said. But I don't have the source of the quote. What is usually advised is actually that if you are going to copy your arguments in your function anyway, don't. Just do it in the parameter list (via pass by value). This will allow your function to move r-value arguments straight to their destination. When you pass l-values, they will be copied, but you were going to do that anyway.
If you are going to make an internal copy, then passing by value will do exactly one move construct more than the pair of overloads (pass by rvalue ref)+(pass by const lvalue ref).
If move construct is cheap, this is a small amount of runtime overhead in exchange for less compile time and code maintenance overhead.
The idiom is "Want speed? Making a copy anyhow? Pass by value, instead of by const lvalue reference." in reality.
Finally, your benchmark is flawed as you failed to reserve(enough) before your push backs. Reallocation can cause extra operations. Oh, and make your move constructor noexcept, as conforming libraries will prefer a copy to a move if move can throw in many situations.
I was reading the difference between direct-initialization and copy-initialization (§8.5/12):
T x(a); //direct-initialization
T y = a; //copy-initialization
What I understand from reading about copy-initialization is that it needs accessible & non-explicit copy-constructor, or else the program wouldn't compile. I verified it by writing the following code:
struct A
{
int i;
A(int i) : i(i) { std::cout << " A(int i)" << std::endl; }
private:
A(const A &a) { std::cout << " A(const A &)" << std::endl; }
};
int main() {
A a = 10; //error - copy-ctor is private!
}
GCC gives an error (ideone) saying:
prog.cpp:8: error: ‘A::A(const A&)’ is private
So far everything is fine, reaffirming what Herb Sutter says,
Copy initialization means the object is initialized using the copy constructor, after first calling a user-defined conversion if necessary, and is equivalent to the form "T t = u;":
After that I made the copy-ctor accessible by commenting the private keyword. Now, naturally I would expect the following to get printed:
A(const A&)
But to my surprise, it prints this instead (ideone):
A(int i)
Why?
Alright, I understand that first a temporary object of type A is created out of 10 which is int type, by using A(int i), applying the conversion rule as its needed here (§8.5/14), and then it was supposed to call copy-ctor to initialize a. But it didn't. Why?
If an implementation is permitted to eliminate the need to call copy-constructor (§8.5/14), then why is it not accepting the code when the copy-constructor is declared private? After all, its not calling it. Its like a spoiled kid who first irritatingly asks for a specific toy, and when you give him one, the specific one, he throws it away, behind your back. :|
Could this behavior be dangerous? I mean, I might do some other useful thing in the copy-ctor, but if it doesn't call it, then does it not alter the behavior of the program?
Are you asking why the compiler does the access check? 12.8/14 in C++03:
A program is ill-formed if the copy
constructor or the copy assignment
operator for an object is implicitly
used and the special member function
is not accessible
When the implementation "omits the copy construction" (permitted by 12.8/15), I don't believe this means that the copy ctor is no longer "implicitly used", it just isn't executed.
Or are you asking why the standard says that? If copy elision were an exception to this rule about the access check, your program would be well-formed in implementations that successfully perform the elision, but ill-formed in implementations that don't.
I'm pretty sure the authors would consider this a Bad Thing. Certainly it's easier to write portable code this way -- the compiler tells you if you write code that attempts to copy a non-copyable object, even if the copy happens to be elided in your implementation. I suspect that it could also inconvenience implementers to figure out whether the optimization will be successful before checking access (or to defer the access check until after the optimization is attempted), although I have no idea whether that warranted consideration.
Could this behavior be dangerous? I
mean, I might do some other useful
thing in the copy-ctor, but if it
doesn't call it, then does it not
alter the behavior of the program?
Of course it could be dangerous - side-effects in copy constructors occur if and only if the object is actually copied, and you should design them accordingly: the standard says copies can be elided, so don't put code in a copy constructor unless you're happy for it to be elided under the conditions defined in 12.8/15:
MyObject(const MyObject &other) {
std::cout << "copy " << (void*)(&other) << " to " << (void*)this << "\n"; // OK
std::cout << "object returned from function\n"; // dangerous: if the copy is
// elided then an object will be returned but you won't see the message.
}
C++ explicitly allows several optimizations involving the copy constructor that actually change the semantics of the program. (This is in contrast with most optimizations, which do not affect the semantics of the program). In particular, there are several cases where the compiler is allowed to re-use an existing object, rather than copying one, if it knows that the existing object will become unreachable. This (copy construction) is one such case; another similar case is the "return value optimization" (RVO), where if you declare the variable that holds the return value of a function, then C++ can choose to allocate that on the frame of the caller, so that it doesn't need to copy it back to the caller when the function completes.
In general, in C++, you are playing with fire if you define a copy constructor that has side effects or does anything other than just copying.
In any compiler, syntax [and semantic] analysis process are done prior to the code optimization process.
The code must be syntactically valid otherwise it won't even compile. Its only in the later phase (i.e code optimization) that the compiler decides to elide the temporary that it creates.
So you need an accessible copy c-tor.
Here you can find this (with your comment ;)):
[the standard] also says that the temporary copy
can be elided, but the semantic
constraints (eg. accessibility) of the
copy constructor still have to be
checked.
RVO and NRVO, buddy. Perfectly good case of copy ellision.
This is an optimization by the compiler.
In evaluating: A a = 10; instead of:
first constructing a temporary object through A(int);
constructing a through the copy constructor and passing in the temporary;
the compiler will simply construct a using A(int).