简体   繁体   中英

Am I initializing my C++ reference variables correctly?

I've tried to Google this issue, and I can't find anything that I see as relevant. So I must be looking for the wrong thing; none the less, I'd appreciate some advice...

Foobar &foobar = *new Foobar(someArg, anotherArg);

Is it just me or does that seem smelly?

I understand that the new keyword is designed for use with pointers (as such):

Foobar *foobar = new Foobar(someArg, anotherArg);

But what if you don't require a pointer on that instance, and you would like to use a reference instead? Or, is it the case that you don't need to explicitly initialize it (much like local variables); and if this is the case, what if I want to initialize with parameters?

The following does not work (unless I'm doing something wrong):

// the last argument is of type: int
Foobar &foobar(someArg, anotherArg);

... gives the compiler error:

initializer expression list treated as compound expression invalid initialization of non-const reference of type 'Foobar&' from a temporary of type 'int'

And also this doesn't seem to work:

Foobar &foobar = Foobar(someArg, anotherArg);

... gives the compiler error:

error: invalid initialization of non-const reference of type 'Foobar&' from a temporary of type 'Foobar'

Update 1:

Bare in mind that I am returning this value, so I don't want to use a local variable; I want to use a value on the heap, not the stack:

Foobar &helloWorld()
{
    Foobar &foobar = *new Foobar(someArg, anotherArg);
    foobar.HelloWorld();
    return foobar;
}

Should I just be using pointers instead, or is this completely valid?

Why do you think you need to use new and references at all? Why not:

Foobar foobar(someArg, anotherArg);

For your function - return a value:

Foobar helloWorld()
{
    Foobar foobar(someArg, anotherArg);
    foobar.HelloWorld();
    return foobar;
}

or a pointer:

Foobar * helloWorld()
{
    Foobar * foobar = new Foobar(someArg, anotherArg);
    foobar->HelloWorld();
    return foobar;
}

If you do this - the caller is responsible for deleting the allocated object at some point.

Return from a non-member function is one place where references can typically not be used sensibly, as the thing you would like to refer to usually no longer exists.

Yes, that is smelly!

If you 'new' something, assign it to a pointer (or smart-pointer type), as it will need to be deleted again to avoid a memory leak. References aren't conventionally thought of as being things you need to delete again, so if somebody else sees that code (assigning a new'ed object to a reference), it may well confuse them.

You can do...

const Foobar &foobar = Foobar(someArg, anotherArg);

...if you really want a reference. Note that once foobar goes out of scope, the temporary object it is referencing will die. But, there's not a lot of point in writing that when you can straight-forwardly write:

Foobar foobar(someArg, anotherArg);

You probably don't actually need a reference... they're generally (but not exclusively) used for the types of method arguments. This is so that you can pass something that looks like an object, but only has the size of a pointer, and which the method can modify. The reference was introduced primarily to allow you to write a copy constructor (I won't explain that here!).

References in C++ are really not as strong as people expect them to be, I think the confusion comes from people who are used to languages like Java and C# that don't have pointers and have references that can be reassigned and used.

A reference in C++ is generally best used as an alias for a variable, so you can simplify things like parameter passing and return values. There are very few situations where you would try to acquire a reference the way you are doing on the first line. So usually you don't need to do what it seems that you're trying to do :)

The second line is of course correct, and you could do something like return *foobar from a function that returns a reference.

Your writing it right. But keep in mind its weird to free the ptr by doing delete &refVar; (it could be mistaken for a variable that was not created by new).

You should check out GotW for good practices passing around http://www.gotw.ca/gotw/ I dont remember which lesson it was (there was more then one) but reading through that is more valuable then anyone realize (gotchas will be less of a surprise)

You should try writing code that NEVER use pointers. I do it but once got stuck when i needed a container of BaseObj. There was no working around that. Typically i used the STL containers and have most variable alive on the stack { MyClass myVar; ... } or as a member and pass it around as needed.

Its quiet easy to remove pointers once you start passing reference instead of pointers and use stl containers instead of new. Note that i never use auto_ptr. vector, string, deque, list and map should do most of what you need. There are other containers.

Nope, you've got it. A foo& "points to" the actual object, so if you really want a foo reference you have to dereference the foo pointer.

@Neil has a point, though -- syntactically that's how you get what you want, but why do you want it?

I'd recommend using a smart pointer. You need to manage ownership, and a reference will not do that for you. In fact, it will obscure to the caller that there's any ownership issue at all. As Scott Langham mentioned in a comment, std::auto_ptr would work. Using shared_ptr from Boost or TR1 might be a better idea.

boost::shared_ptr<Foobar> helloWorld()
{
    boost::shared_ptr<Foobar> foobar(new Foobar(someArg, anotherArg));
    foobar->HelloWorld();
    return foobar;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM