I made a class and a struct.
The class is named Learning
and the struct is named Action
.
My Action
constructor takes two parameters: object's name and function, where the name is basically a std::string
and the function is a std::function<int(int)>
.
This is my Action
struct:
typedef std::function<int(int)> func;
struct Action {
// constructor
Action(name, const func&);
/// methods
void setname(name);
void setfunction(const func&);
/// operators
int operator()(int x);
/// members
name ActionName;
func f;
};
My Action
struct is used by my Learning
class by calling this function:
Learning robot;
robot.addAction(Action("Up", [](int y) ->int{return y ; }));
Where the Action
is saved inside an actions
vector in my Learning
class:
class Learning
{
public:
void addAction(Action&);
private:
std::vector<Action> actions;
};
void Learning::addAction(Action& act)
{
actions.push_back(act);
}
The method addAction()
adds the created Action
object into my actions
vector.
I used a lambda expression as the parameter because it looks cleaner.
But when I call actions[0].f(0)
, or actions[0](0)
, I get an exception:
Unhandled exception at 0x00007FFA4DE44F69 in RL_Q.exe: Microsoft C exception: std::bad_function_call at memory location 0x000000C09A7BE4C0.
this is my Action constructor
Action::Action(name name, func f) { setname(name); setfunction(f); }
When I debug this, my function f
is empty after I instantiate my Action
object with given parameters.
How do I solve this?
CodePudding user response:
Your addAction method takes a reference
void addAction(Action&);
Then you call this with an rvalue
robot.addAction(Action("Up", [](int y) ->int{return y ; }));
You can not bind an rvalue to a non-const lvalue reference. Either make the method const ref or rvalue reference.
void addAction(const Action&);
void addAction(Action&&);
CodePudding user response:
You define
Learning::addAction(Action&)
with an action reference as argument. This means that you have to ensure the lifetime of the referenced object, and not let it get destroyed by going out of scope. But then you call it on an rvalue
// Action(...) immediately goes out of scope
robot.addAction(Action("Up", [](int y) ->int{return y ; }));
Therefore the references you put in your vectors are all invalid : they point toward long gone objects. You need to take ownership of them if you want it to work. This means :
class Learning
{
public:
void addAction(Action&&);
private:
std::vector<Action> actions;
};
// rvalue reference, so the vector can take ownership of the expiring object
void Learning::addAction(Action&& act)
{
actions.push_back(std::move(act));
}