Why is the copy ctor invoked twice when using std::bind? - c++

I am playing around with std::function and std::bind to understand how arguments are copied around and if I can save some of the copy operations.
I understand that when using std::bind, the arguments are passed by value and not reference (unless std::ref is specified). However, when I run the following snippet, the copy constructor is invoked twice. Can someone explain why?
struct token
{
static int i;
int code;
token()
: code(i++)
{
cout << __FUNCTION__ << ": " << code << endl;
}
virtual ~token()
{
cout << __FUNCTION__ << endl;
}
token (token const & other)
: code (other.code)
{
cout << "copy ctor: " << code << endl;
}
// update -- adding a move ctor
token (token const && other)
: code (std::move(other.code))
{
cout << "move ctor: " << code << endl;
}
// update -- end
void boo() const
{
cout << __FUNCTION__ << ": " << code << endl;
}
};
void call_boo(token const & t)
{
t.boo();
}
int main()
{
token t2;
cout << "default" << endl;
std::function< void () >(std::bind(&call_boo, t2));
cout << "ref" << endl;
std::function< void () >(std::bind(&call_boo, std::ref(t2)));
cout << "move" << endl;
std::function< void () >(std::bind(&call_boo, std::move(t2)));
cout << "end" << endl;
return 0;
}
When run, this produces the following output:
token: 1
default
// Without move ctor
// copy ctor: 1 // Makes sense. This is the passing by value.
// copy ctor: 1 // Why does this happen?
// With move ctor
copy ctor: 1
move ctor: 1
~token
~token
ref // No copies. Once again, makes sense.
move
// Without move ctor
// copy ctor: 1
// copy ctor: 1
// With move ctor
move ctor: 1
move ctor: 1
~token
~token
end
~token

Parameters for this constructor of std::function are always copied, so a copy of the bind object (which itself has a copy of your token object) is created inside the std::function.
http://en.cppreference.com/w/cpp/utility/functional/function/function
template< class F >
function( F f );
5) Initializes the target with a copy of f. If f is a null pointer to function or null pointer to member, *this will be empty after the call. This constructor does not participate in overload resolution unless f is Callable for argument types Args... and return type R. (since C++14)

Related

Why would std::initializer_list copy items?

I always thought std::initializer_list is a lightweight proxy object which would only take const references from list items, instead of copy them.
But then I discovered that copy is actually performed in this case:
struct Test {
Test() {
std::cout << this << " default ctor" << std::endl;
}
Test(const Test&) {
std::cout << this << " copy ctor" << std::endl;
}
~Test() {
std::cout << this << " destructor" << std::endl;
}
};
int main() {
Test a;
Test b;
Test c;
std::cout << "for begin" << std::endl;
for(const auto& current : {a, b, c}) {
std::cout << "Current: " << &current << std::endl;
}
std::cout << "for end" << std::endl;
}
Output of above code:
0x63e5acda default ctor
0x63e5acdb default ctor
0x63e5acdc default ctor
for begin
0x63e5acdd copy ctor
0x63e5acde copy ctor
0x63e5acdf copy ctor
Current: 0x63e5acdd
Current: 0x63e5acde
Current: 0x63e5acdf
0x63e5acdf destructor
0x63e5acde destructor
0x63e5acdd destructor
for end
0x63e5acdc destructor
0x63e5acdb destructor
0x63e5acda destructor
Why would std::initializer_list copy items in this case, instead of just taking their references? Is there any "elegant" way to write things similar to for(auto&& x : {a, b, c}), but without copying existing items?
From the documentation on std::initializer_list:
The underlying array is a temporary array of type const T[N], in which each element is copy-initialized (except that narrowing conversions are invalid) from the corresponding element of the original initializer list. The lifetime of the underlying array is the same as any other temporary object, except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary (with the same exceptions, such as for initializing a non-static class member). The underlying array may be allocated in read-only memory.

Strange object assignment behaviour c++

I have a strange behavior with object assignments. I will much appreciate, if you can explain why this assignment works like this. It has cost me already a lot of time.
I am using Visual Studio Enterprise 2017 (all default settings).
Code:
#include "stdafx.h"
#include <iostream>
using namespace std;
class Test
{
public:
Test()
{
cout << "Constructor of " << this << endl;
}
~Test()
{
cout << "Destructor of " << this << endl;
}
};
int main()
{
cout << "Assignment 1" << endl;
auto t = Test();
cout << "Assignment 2" << endl;
t = Test();
int i = 0;
cin >> i;
return 0;
}
Output (up to cin):
Assignment 1
Constructor of 006FFC9F
Assignment 2
Constructor of 006FFBC7
Destructor of 006FFBC7
Expected Output (up to cin):
Assignment 1
Constructor of 006FFC9F
Assignment 2
Destructor of 006FFC9F
Constructor of 006FFBC7
I wanted to write a test function which creates an object of my (template) class, do some tests, then create a new object and do some more testing. The problem is that t holds the already destructed object after the second assignment.
I know that I can just use dynamic allocation which results in the expected behavior, but why does this program behave different?
Thank you very much.
Regards.
PS: Results are the same, independent of Release/Debug or 64/32 bit compilation
EDIT: More verbose example:
#include "stdafx.h"
#include <iostream>
using namespace std;
class Test
{
private:
float* val;
public:
Test()
{
val = new float;
cout << "Constructor of " << this << ", addr. of val: " << val << endl;
}
~Test()
{
cout << "Destructor of " << this << ", addr. of val: " << val << " --> DELETING VAL!" << endl;
delete val;
}
float* getVal() { return this->val; }
};
int main()
{
cout << "Assignment 1" << endl;
auto t = Test();
cout << "Assignment 2" << endl;
t = Test();
cout << "Val Address: " << t.getVal() << endl;
int i = 0;
cin >> i;
return 0;
}
Output (it holds a deleted pointer at the end!!!):
Assignment 1
Constructor of 004FFBDC, addr. of val: 0072AEB0
Assignment 2
Constructor of 004FFB04, addr. of val: 00723928
Destructor of 004FFB04, addr. of val: 00723928 --> DELETING VAL!
Val Address: 00723928
With
auto t = Test();
you actually construct two objects. First is the Test() which constructs a temporary object. The second is the construction of t which is made through copy-construction. There is no assignment being made here, even if the = operator is used, it's copy-construction.
If you add a copy-constructor to the Test class similar to your constructor and destructor, you should see it clearly.
As for
t = Test();
here a temporary object is created with Test(). That temporary object is then passed to the (compiler-generated) assignment operator of the Test class, and then the temporary object is promptly destructed.
The object t itself is not destructed, it should not be as it is the destination of the assignment.
Your confusion seems to be a mistaken expectation that the original object is destroyed when assignment takes place. Like, in this code:
cout << "Assignment 2" << endl;
t = Test();
This piece of code invokes the move-assign operator. Since you didn't define one, the default one generated by the compiler is more-or-less going to look like this:
Test & operator=(Test &&) {}
Note how there's no invocation of a constructor or (critically) a destructor in that code. The only Constructors and Destructors that are going to run are on the temporary object (which is what you observe in the actual output). The original object doesn't get destroyed until the code goes out of scope; and why would it? It's not like you can stop using the stack space before then.
Edit: Something which might help you understand what's going on:
#include<iostream>
struct Test {
Test() {std::cout << "Constructed.\n";}
~Test() {std::cout << "Destructed.\n";}
Test(Test const&) {std::cout << "Copy-Constructed.\n";}
Test(Test &&) {std::cout << "Move-Constructed.\n";}
Test & operator=(Test const&) {std::cout << "Copy-Assigned.\n"; return *this;}
Test & operator=(Test &&) {std::cout << "Move-Assigned.\n"; return *this;}
};
int main() {
std::cout << "Test t;\n";
Test t; //Construction
std::cout << "Test t2(t);\n";
Test t2(t); //Copy-Construct
std::cout << "Test t3(std::move(t2));\n";
Test t3(std::move(t2)); //Move-Construct
std::cout << "Test t4 = t;\n";
Test t4 = t; //Copy Construct, due to Copy Ellision
std::cout << "Test t5 = Test();\n";
Test t5 = Test(); //Will probably be a normal Construct, due to Copy Ellision
std::cout << "t = t2;\n";
t = t2; //Copy Assign
std::cout << "t = Test();\n";
t = Test(); //Move Assign, will invoke Constructor and Destructor on temporary
std::cout << "Done! Cleanup will now happen!\n";
return 0;
}
Results as seen when compiled here:
Test t;
Constructed.
Test t2(t);
Copy-Constructed.
Test t3(std::move(t2));
Move-Constructed.
Test t4 = t;
Copy-Constructed.
Test t5 = Test();
Constructed.
t = t2;
Copy-Assigned.
t = Test();
Constructed.
Move-Assigned.
Destructed.
Done! Cleanup will now happen!
Destructed.
Destructed.
Destructed.
Destructed.
Destructed.
DOUBLE EDIT COMBO!:
As I mentioned in comments, val is just a pointer. 8 bytes (on a 64-bit machine) allocated as part of Test's storage. If you're trying to make sure that Test always contains a valid value for val that hasn't been deleted, you need to implement the Rule of Five (previously known as the Rule of Three):
class Test {
float * val;
public:
Test() {val = new float;}
~Test() {delete val;
Test(Test const& t) {
val = new float(*(t.val));
}
Test(Test && t) {std::swap(val, t.val);}
Test & operator=(Test const& t) {
float * temp = new float(*(t.val)); //Gives Strong Exception Guarantee
delete val;
val = temp;
return *this;
}
Test & operator=(Test && t) {std::swap(val, t.val); return *this;};
float & get_val() const {return *val;} //Return by reference, not by pointer, to
//prevent accidental deletion.
};

std::pair move not elided on definition?

I noticed something very strange with Visual Studio 2012: Defining a pair object like so:
auto objp = pair<int, LogMe>();
will not elide the copy/move of the pair in VC11, this call will print:
LogMe::LogMe - def.ctor!
LogMe::LogMe - move.ctor!
LogMe::~LogMe - dtor!
that is, a temporary pair will be created and then moved into the objp variable. (declaring it as pair<...> obj; only logs the default ctor)
I have cross checked with my LogMe test object alone:
cout << "# Construct Object via auto obj = ...\n";
auto obj = LogMe();
# Construct Object via auto obj = ...
LogMe::LogMe - def.ctor!
and here the assignment will be elided.
This seems to be specific to VC11, as testing it in IDEOne (which uses gcc 4.8.1) shows that the extraneous move is elided always there.
What's going on here? Not being able to rely on the initialization copy being elided makes me nervous.
Note: Tests for release vs. debug version show the same result. (Which I would have expected, as copy-elision is performed independently of optimization flags in MSVC.)
Full sourcecode to test (See also the ideone link):
#include "stdafx.h"
#include <iostream>
#include <map>
using namespace std;
struct LogMe {
std::string member;
LogMe() {
cout << __FUNCTION__ << " - def.ctor!" << endl;
}
~LogMe() {
cout << __FUNCTION__ << " - dtor!" << endl;
}
LogMe(LogMe const&) {
cout << __FUNCTION__ << " - cpy.ctor!" << endl;
}
LogMe& operator=(LogMe const&) {
cout << __FUNCTION__ << " - cpy.assign.op!" << endl;
return *this;
}
LogMe(LogMe&&) {
cout << __FUNCTION__ << " - move.ctor!" << endl;
}
LogMe& operator=(LogMe&&) {
cout << __FUNCTION__ << " - move.assign.op!" << endl;
return *this;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
{
cout << "# Construct Object via auto obj = ...\n";
auto obj = LogMe();
cout << "# Construct pair<int, object> via auto objp = ...\n";
auto objp = pair<int, LogMe>();
cout << "# Construct pair<int, object> via pair objp2; ...\n";
pair<int, LogMe> p2;
}
return 0;
It appears it is not the move ctor, nor the templated move ctor that is causing the problem, but the presence of enable_if<is_convertable<... in the templated move ctor:
Testing with just an object, throwing auto and pair out of the test:
OK, copy/move elided:
cout << "# Construct Object: auto obj = LogMe();\n";
LogMe obj = LogMe();
LogMe(LogMe&&) {
cout << __FUNCTION__ ...
}
And, with a test like so:
cout << "# Construct Object: LogMeTempl obj = LogMeTempl();\n";
LogMeTempl obj = LogMeTempl();
cout << "# Construct Object: LogMeTempl obj2;\n";
LogMeTempl obj2;
OK, copy move also elided:
template<class Other>
LogMeTempl(Other&& rhs
// , typename enable_if<is_convertible<Other, LogMeTempl>::value, void>::type ** = 0
) {
cout << __FUNCTION__ << ...;
}
Fail! Move ctor invoked!
template<class Other>
LogMeTempl(Other&& rhs
, typename enable_if<is_convertible<Other, LogMeTempl>::value, void>::type ** = 0
) {
cout << __FUNCTION__ << ...;
}
And note that the enable_if can be reduced to enable_if<true, void>::type** = 0 - if fact any additional defaulted parameter will do (e.g. , int defaulted_param_on_move_ctor = 0 and it will still prevent the move elision).
This also extends to a type with a copy-ctor only that has a default argument. It won't be elided either. A quick cross-check with gcc shows there doesn't seem to be any such problem there.
Short Answer
Types with defaulted arguments in their copy/move ctor don't have their initialization copy/move elided.
I have added a bug on MS.connect for this issue.
I have also added a test-case for (N)RVO to IDEone. Even without the default argument, *N*RVO seems to work better in gcc than VC++.

Passing/Moving parameters of a constructor in C++0x

If I have a constructor with n parameters such that any argument to that can be an rvalue and lvalue. Is it possible to do support this with move semantics for the rvalues without writing 2^n constructors for each possible rvalue/lvalue combination?
You take each one by value, like this:
struct foo
{
foo(std::string s, bar b, qux q) :
mS(std::move(s)),
mB(std::move(b)),
mQ(std::move(q))
{}
std::string mS;
bar mB;
qux mQ;
};
The initialization of the function parameters by the argument will either be a copy-constructor or move-constructor. From there, you just move the function parameter values into your member variables.
Remember: copy- and move-semantics are a service provided by the class, not by you. In C++0x, you no longer need to worry about how to get your own "copy" of the data; just ask for it and let the class do it:
foo f("temporary string is never copied", bar(), quz()); // no copies, only moves
foo ff(f.mS, f.mB, f.mQ); // copies needed, will copy
foo fff("another temp", f.mB, f.mQ); // move string, copy others
Note: your constructor only takes in values, those values will figure out how to construct themselves. From there, of course, it's up to you to move them where you want them.
This applies everywhere. Have a function that needs a copy? Make it in the parameter list:
void mutates_copy(std::string s)
{
s[0] = 'A'; // modify copy
}
mutates_copy("no copies, only moves!");
std::string myValue = "don't modify me";
mutates_copy(myValue); // makes copy as needed
mutates_copy(std::move(myValue)); // move it, i'm done with it
In C++03, you could emulate it fairly well, but it wasn't common (in my experience):
struct foo
{
foo(std::string s, bar b, qux q)
// have to pay for default construction
{
using std::swap; // swaps should be cheap in any sane program
swap(s, mS); // this is effectively what
swap(b, mB); // move-constructors do now,
swap(q, mQ); // so a reasonable emulation
}
std::string mS;
bar mB;
qux mQ;
};
Take the following code ideone link.
#include <iostream>
class A
{
public:
A() : i(0) {}
A(const A& a) : i(a.i) { std::cout << "Copy A" << std::endl; }
A(A&& a) : i(a.i) { std::cout << "Move A" << std::endl; }
int i;
};
template <class T>
class B1
{
public:
template <class T1, class T2>
B1(T1&& x1_, T2&& x2_) : x1(std::forward<T1>(x1_)), x2(std::forward<T2>(x2_)) {}
B1(const B1<T>& x) : x1(x.x1), x2(x.x2) { std::cout << "Copy B1" << std::endl; }
B1(B1<T>&& x) : x1(std::move(x.x1)), x2(std::move(x.x2)) { std::cout << "Move B1" << std::endl; }
private:
T x1;
T x2;
};
template <class T>
class B2
{
public:
B2(T x1_, T x2_) : x1(std::move(x1_)), x2(std::move(x2_)) {}
B2(const B2<T>& x) : x1(x.x1), x2(x.x2) { std::cout << "Copy B2" << std::endl; }
B2(B2<T>&& x) : x1(std::move(x.x1)), x2(std::move(x.x2)) { std::cout << "Move B2" << std::endl; }
private:
T x1;
T x2;
};
A&& inc_a(A&& a) { ++a.i; return static_cast<A&&>(a); }
A inc_a(const A& a) { A a1 = a; ++a1.i; return a1; }
int main()
{
A a1;
A a2;
std::cout << "1" << std::endl;
B1<A> b1(a1,a2);
std::cout << "2" << std::endl;
B1<A> b2(a1,A());
std::cout << "3" << std::endl;
B1<A> b3(A(),a2);
std::cout << "4" << std::endl;
B1<A> b4(A(),A());
std::cout << "5" << std::endl;
B2<A> b5(a1,a2);
std::cout << "6" << std::endl;
B2<A> b6(a1,A());
std::cout << "7" << std::endl;
B2<A> b7(A(),a2);
std::cout << "8" << std::endl;
B2<A> b8(A(),A());
std::cout << "9" << std::endl;
std::cout << std::endl;
std::cout << "11" << std::endl;
B1<A> b11(a1,a2);
std::cout << "12" << std::endl;
B1<A> b12(a1,inc_a(A()));
std::cout << "13" << std::endl;
B1<A> b13(inc_a(A()),a2);
std::cout << "14" << std::endl;
B1<A> b14(inc_a(A()),inc_a(A()));
std::cout << "15" << std::endl;
B2<A> b15(a1,a2);
std::cout << "16" << std::endl;
B2<A> b16(a1,inc_a(A()));
std::cout << "17" << std::endl;
B2<A> b17(inc_a(A()),a2);
std::cout << "18" << std::endl;
B2<A> b18(inc_a(A()),inc_a(A()));
std::cout << "19" << std::endl;
}
Which outputs the following:
1
Copy A
Copy A
2
Copy A
Move A
3
Move A
Copy A
4
5
Copy A
Copy A
Move A
Move A
6
Copy A
Move A
Move A
7
Copy A
Move A
Move A
8
9
11
Copy A
Copy A
12
Copy A
Move A
13
Move A
Copy A
14
Move A
Move A
15
Copy A
Copy A
Move A
Move A
16
Move A
Copy A
Move A
Move A
17
Copy A
Move A
Move A
Move A
18
Move A
Move A
Move A
Move A
19
As can be seen, the pass by value approach in B2 causes extra move for each argument in all cases except for when the argument is a prvalue.
If you want best performance, I suggest the template approach in B1. This way you have effectively have separate code for the copy and move cases, and hence only a single copy or a single move required. In the pass by value approach, at least two move/copies are required, except for the prvalue case where the compiler can construct the value in the place of the argument, in which as only one move is required.
Depending on what c++ compiler you are using, you could look into "functions with variable argument lists"
The idea is that you can pass in as many parameters as you want to the method and it just populates into an array that you can loop through.
For microsoft c++, the following blogposts might be helpful:
http://msdn.microsoft.com/en-us/library/fxhdxye9(v=VS.100).aspx
http://blogs.msdn.com/b/slippman/archive/2004/02/16/73932.aspx

Why only one object gets constructed but multiple objects are destroyed when using functor?

The following example, beats me. I've been so far thinking, that when functor is being used, the object gets constructed once and the same object is used multiple times, when used with for_each algorithm and that seems to be correct.
However, even though, only one object gets constructed, but multiple objects are destroyed. Now, this beats me.
class print
{
public:
void operator()(int i)
{
std::cout << i << std::endl;
}
print()
{
std::cout << "Constructor " << std::endl;
}
~print()
{
std::cout << "Destructor" << std::endl;
}
};
int main()
{
std::vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
std::cout << "After assigning values " << std::endl;
for_each(v.begin() , v.end() , print());
std::cout << "After printing values " << std::endl;
}
The output is as follows
After assigning Values
Constructor
10
20
30
Destructor
Destructor
Destructor
After printing values.
How is this possible?
Don't forget about the copy constructor (the Rule of Three can help you to remember this):
class print
{
public:
void operator()(int i)
{
std::cout << i << std::endl;
}
print()
{
std::cout << "Constructor " << std::endl;
}
print(const print& other) {
std::cout << "Copy Constructor " << std::endl;
}
~print()
{
std::cout << "Destructor" << std::endl;
}
};
int main()
{
std::vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
std::cout << "After assigning values " << std::endl;
for_each(v.begin() , v.end() , print());
std::cout << "After printing values " << std::endl;
}
Output:
After assigning values
Constructor
Copy Constructor
10
20
30
Copy Constructor
Destructor
Destructor
Destructor
After printing values
Here is how I have for_each on my system:
template<class _InIt,
class _Fn1> inline
_Fn1 _For_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{ // perform function for each element
for (; _First != _Last; ++_First)
_Func(*_First);
return (_Func); // a copy could be created here (C3)
}
template<class _InIt,
class _Fn1> inline
_Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func)
{ // perform function for each element
_DEBUG_RANGE(_First, _Last);
_DEBUG_POINTER(_Func);
return (_For_each(_Unchecked(_First), _Unchecked(_Last), _Func)); // a copy created here (C2)
}
So, essentially, this is how it could look
for_each(v.begin() , v.end() , print()); // print functor created (constructor)
// a copy created here (C1)
Now, this is completely upto the implementation if copy elision is done or not. The Standard does allow that latitude to elide away the copy constructor e.g. C3 may be eliminated.
A good way to control gcc behavior here is the -fno-elide-constructors which ensures that code does not elide away the copy constructor
You are only printing "Constructor" from the default constructor. Instances of your type can come into existance from the copy-constructor as well. Copies might be being made through the call stack. Unless you specify otherwise you get a default copy constructor for free. You can add a copy constructor and also print out "Constructor" if you want to verify this.
No matter how it's constructed, you will still see the one-and-only destructor fire and print-out "Destructor".
I would say that the for_each created copies of the print() functor which calls the implicit copy constructor defined by the compiler which doesn't appear in your code (not the same as your defined constructor above).