• Create Account

### #ActualWashu

Posted 02 May 2012 - 02:02 AM

Wow, great.
Please all, explain me in a way I can actually understand. I have never been given the opportunity of reading the official C/C++ ISO spec nor to spend my effort at looking for language design in details.

This line:
Callbacks one(lines); // (1)
Constructs a Callbacks passing in a lambda. Since lambda is not a valid type for the constructor of Callbacks, a temporary object of type std::function<void()> is constructed instead and passed. Since you indicate the parameter as a CONSTANT REFERENCE, you can pass an unnamed temporary value (such as the std::function<void()> just constructed).

The instant that line is done evaluated the TEMPORARY VALUE that was constructed is destructed. Your Callbacks class now holds a reference to an unnamed temporary that no longer exists.

In fact, you can make it explicit (but with the same bug):
Callbacks one(PrintFunc(lines)); // (1)

by changing this line:
PrintFunc const& func; // (2)
to
PrintFunc func; // (2)
you cause your constructor to invoke the function copy constructor, taking the unnamed temporary you passed and copying it. Thus avoiding holding on to a reference to a soon to be dead object.

Thus the corrected code:

#include <iostream>
#include <functional>

using namespace std;
typedef function<void()> PrintFunc;

void Nothing(const PrintFunc &blah) {
blah();
}
void Nothing_value(const PrintFunc blah) {
blah();
}

struct Callbacks {
PrintFunc func; // (2)
Callbacks(PrintFunc const& call) : func(call) { }
};

int main() {
auto lines = []() { cout<<"- - - - - -"<<endl; };
auto dots  = []() { cout<<". . . . . ."<<endl; };
Nothing(lines);
Nothing_value(dots);
{
Callbacks one(lines); // (1)
one.func();
}
{
Callbacks two(dots);
two.func();
}
return 0;
}

### #3Washu

Posted 02 May 2012 - 02:01 AM

Wow, great.
Please all, explain me in a way I can actually understand. I have never been given the opportunity of reading the official C/C++ ISO spec nor to spend my effort at looking for language design in details.

This line:
Callbacks one(lines); // (1)
Constructs a Callbacks passing in a lambda. Since lambda is not a valid type for the constructor of Callbacks, a temporary object of type std::function<void()> is constructed instead and passed. Since you indicate the parameter as a CONSTANT REFERENCE, you can pass an unnamed temporary value (such as the std::function<void()> just constructed).

The instant that line is done evaluated the TEMPORARY VALUE that was constructed is destructed. Your Callbacks class now holds a reference to an unnamed temporary that no longer exists.

In fact, you can make it explicit (but with the same bug):
Callbacks one(PrintFunc(lines)); // (1)

by changing this line:
PrintFunc const& func; // (2)
to
PrintFunc func; // (2)
you cause your constructor to invoke the function copy constructor, taking the unnamed temporary you passed and copying it. Thus avoiding holding on to a reference to a soon to be dead object.

### #2Washu

Posted 02 May 2012 - 01:59 AM

Wow, great.
Please all, explain me in a way I can actually understand. I have never been given the opportunity of reading the official C/C++ ISO spec nor to spend my effort at looking for language design in details.

This line:
Callbacks one(lines); // (1)
Constructs a Callbacks passing in a lambda. Since lambda is not a valid type for the constructor of Callbacks, a temporary object of type std::function<void()> is constructed instead and passed. Since you indicate the parameter as a CONSTANT REFERENCE, you can pass an unnamed temporary value (such as the std::function<void()> just constructed).

The instant that line is done evaluated the TEMPORARY VALUE that was constructed is destructed. Your Callbacks class now holds a reference to an unnamed temporary that no longer exists.

In fact, you can make it explicit (but with the same bug):
Callbacks one(PrintFunc(lines)); // (1)

### #1Washu

Posted 02 May 2012 - 01:59 AM

Wow, great.
Please all, explain me in a way I can actually understand. I have never been given the opportunity of reading the official C/C++ ISO spec nor to spend my effort at looking for language design in details.

This line:
Callbacks one(lines); // (1)
Constructs a Callbacks passing in a lambda. Since lambda is not a valid type for the constructor of Callbacks, a temporary object of type std::function<void()> is constructed instead and passed. Since you indicate the parameter as a CONSTANT REFERENCE, you can pass an unnamed temporary value (such as the std::function<void()> just constructed).

The instant that line is done evaluated the TEMPORARY VALUE that was constructed is destructed. Your Callbacks class now holds a reference to an unnamed temporary that no longer exists.

PARTNERS