What exactly std::function
constructor does when stored in a container ?
In this test codes:
struct A {
int sn;
A() = delete;
A(int v) : sn(v) { cout << "A::init(" << sn << ')' << endl; }
A(const A& a) : sn(a.sn+1) { cout << "A::copy(" << sn << ')' << endl; }
A(A&& a) : sn(a.sn+1) { cout << "A::move(" << sn << ')' << endl; }
~A() { cout << "A::delete(" << sn << ')' << endl; }
};
void func(int a, A &b) {
cout << "func2:" << a << ',' << b.sn << endl;
}
int main(int argc, char *argv[]) {
std::vector<std::function<void(void)>> fv;
A a(1);
cout << "call bind()" << endl;
fv.emplace_back(std::bind(func,1,a));
fv.front()();
cout << "end of local scope" << endl;
}
I declare the move and copy constructors of class A
to accumulate a sequence number, so that I can track it as the Nth created instance. The result is:
A::init(1)
call bind()
A::copy(2)
A::move(3)
A::move(4)
A::delete(3)
A::delete(2)
func2:1,4
end of local scope
A::delete(1)
A::delete(4)
First an instance a(1)
is created in main()
local scope, then it's copied as a new instance a(2)
when calling std::bind()
, then moved again into std::function
dynamically allocated memory (or its internal memory footage?) to hold a copy of std::bind()
instance, so we have the 3rd instances of A
held by std::function
instance.
So far it's understandable, but why is there another move construction ? And why the 3rd instance is destructed before the 2nd instance, which is supposed to be cleared when std::bind()
returns ?
If I rewrite the main()
function as:
int main(int argc, char *argv[]) {
A a(1);
cout << "call bind()" << endl;
std::function<void(void)> f(std::bind(func,1,a));
f();
cout << "end of local scope" << endl;
}
then the result would be:
A::init(1)
call bind()
A::copy(2)
A::move(3)
A::delete(2)
func2:1,3
end of local scope
A::delete(3)
A::delete(1)
There is no second move construction and everything looks reasonable.
What exactly happened when calling emplace_back()
to create std::function
instance in this case ?