Sign in to follow this  
Ro_Akira

C++ hidden reference traps

Recommended Posts

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).

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Yet another reason why implicit conversions are a Bad Thing.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
Well, yes, there is a better way. Don't implement a constructor from a const argument at all, because you can't.

Share this post


Link to post
Share on other sites
Do you mean basically leave out the "InitialisingFactory1 (const Initialiser1& p_init1)" constructor in this instance?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this