C++ hidden reference traps

Started by
4 comments, last by Ro_Akira 16 years, 10 months ago
What I mean by a 'reference trap':

struct Thing
{
    Thing (Foo& p_f) : f (p_f) {}
    Foo& f;
};

// Bar has an implicit conversion to a Foo
Bar b;
Thing t (b);
void Function (t);

Because of the implicit conversion, a temporary object, of type Foo is created when 'b' is passed to the constructor of 't'. But when the constructor for 't' is finished, the temp Foo object is destroyed. By the time 'Function' is called with 't', the Foo object 't.f' is referencing is long gone. Is there any chance of compilers ever being able to catch these types of bugs? I've found it to be pretty nasty because Debug builds appear to frequently survive unscathed, while Release builds crash (Turning on debug information in Release helps out fine, granted).
Advertisement
Actually, a temporary variable may only be passed by const reference, so your example shouldn't compile.

As for compilers being able to catch this sort of thing, not really. They would need to know whether the function called makes a copy or uses a reference, which is impossible if the definition of the function is unavailable. A warning is definitely possible in the other cases, though.
Yet another reason why implicit conversions are a Bad Thing.
Yeah, I do try to avoid implicit conversions most of the time. They're constantly whispering 'convenience!' into my ears however, and sometimes I relent. BTW, do I get bonus points for const_cast? :)

Actual code:
template <typename Type, typename Initialiser1>class InitialisingFactory1 // : Factory<Type>{    public:        InitialisingFactory1 (Initialiser1& p_init1) : init1 (p_init1) {}        InitialisingFactory1 (const Initialiser1& p_init1) :        init1 (const_cast<Initialiser1&> (p_init1)) {}	virtual	Type* operator() (void* address)	{		return new (address) Type (init1);	}	Initialiser1& init1;};// InitialisingFactory2/3/4 for more params

Because 'InitialisingFactory1' is just a temporary transportation (i.e. always on the stack) for constructor parameters, I thought I'd get away with a bit of hackery. Or foolishness, take you pick. :)

I guess the fundamental question is: Is there a better way?
Well, yes, there is a better way. Don't implement a constructor from a const argument at all, because you can't.
Do you mean basically leave out the "InitialisingFactory1 (const Initialiser1& p_init1)" constructor in this instance?

This topic is closed to new replies.

Advertisement