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 set with them:
cubeFunctor cf;
squareFunctor sf;
obj.set(sf, cf);
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 getValue to do
return (*tmp1)(x) + (*tmp2)(x);
To make it look a little prettier (and you still get dynamic dispatch).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With