This is a miniature version of a code I’m running in production. I have found that, my real code, behaves differently under gcc and Intel compilers and my best guess is an undefined behavior. Please consider the following sample code:
#include <iostream>
struct baseFunctor{
virtual double operator()(double x) const = 0;
};
class mathObj{
const baseFunctor *tmp1, *tmp2;
public:
void set(const baseFunctor& b1, const baseFunctor& b2){
tmp1 = &b1;
tmp2 = &b2;
}
double getValue(double x){
return (tmp1->operator()(x) + tmp2->operator()(x));
}
};
int main () {
mathObj obj;
struct squareFunctor: public baseFunctor {
double operator()(double x) const { return x*x; }
};
struct cubeFunctor: public baseFunctor {
double operator()(double x) const { return x*x*x; }
};
obj.set(squareFunctor(), cubeFunctor());
std::cout << obj.getValue(10) << std::endl;
return 0;
}
Could obj.set(squareFunctor(), cubeFunctor()); invoke undefined behavior?
Yes it most definitely does, because you are storing pointers to temporary values that are destroyed at the end of the statement, and then using them. Using a destructed object is undefined behaviour.
You need to create the values separately, and then call
setwith them:Note that you cannot solve this problem by storing the functors by value (unless you use templates), because that would cause slicing.
Also as a side note, you can change
getValueto doTo make it look a little prettier (and you still get dynamic dispatch).