C++ pass-by-reference and factory functions

Started by
7 comments, last by SiCrane 16 years, 3 months ago
I've created a factory function to create an object for me, this object is exposed by an interface ISomething.
void create_something( ISomething& something )
{
  something = *new CSomething();
}
I'm uncertain to what's happening at this point. As I understand it, I'm creating the new instance of CSomething, then dereferencing that pointer to assign to the something reference. The step of derferencing for assignment, how is this really done? Is it okay, or is there a better way of really emphizaing the pass-by-result parameter passing. I'm curious to what type of scemantic will be used. I'm actually concerned that it could take on the reference of a copy of the newly allocated object.
Advertisement
This doesn't work. You're passing a reference to an existing object A. Then, you allocate a new object, B. Then, you use ISomething::operator= to somehow copy a part of B into A (and the operator does not take into account the parts that are not in ISomething, which means that usually it will either cause a compiler error or not copy anything at all). Then, you leak the memory for object B, which you never deallocate. That's it.

If your intent is to create a new object, return it by smart pointer. For shared ownership:
boost::shared_ptr<ISomething> create_something(){  return boost::shared_ptr<ISomething>(new CSomething);}


For simple ownership:
std::auto_ptr<ISomething> create_something(){  return std::auto_ptr<ISomething>(new CSomething);}
Quote:
something = *new CSomething();


This code doesn't do what you think it does.
The code you wrote is very bad. Here is what happens.

// Suppose you do this:ISomething foo;create_something(foo);// Since you passed-by-reference, the function call is equivalent to:foo = *new CSomething();// new CSomething() dynamically allocates memory for a CSomething and returns a// pointer to it. This dynamically allocated memory can *only* be freed by// calling delete on the pointer returned. Unless your "factory function"// expects the users to call delete &foo, you are going to leak memory.


The new operator should only ever return into a pointer. Just remember that every new needs to be followed up with a delete before your program ends.
-----------------------http://poita.org - C++ and D programming articles.
I was thinking of something along the line
class CSomething{public:    int x;};void create_something( CSomething& something ){    something = *new CSomething();    something.x = 1;}int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {    CSomething& something;    create_something(something);    return 0;}
And this doesn't work since a reference cannot be uninitialized.

Are the any particular great uses for reference types? I have a couple in mind, but what would you generally use them for? How do they augment normal pointers?
Quote:Original post by leidegren
I have a couple in mind, but what would you generally use them for? How do they augment normal pointers?


Pointers can be null, references cannot. Therefore, you should use references when you need an object to always be present, and pointers when you need the possibility for an object to be absent.

Using a reference when the object might be absent is impossible. Using a pointer where an object must always be present forces you to assert(ptr) every other line.
Quote:Original post by leidegren
I was thinking of something along the line
void create_something( CSomething& something ){    something = *new CSomething();    something.x = 1;}int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {    CSomething& something;    create_something(something);    return 0;}

The big problem is that you can't assign a reference as if it is a pointer. This works better (but I would simply have the function return a pointer instead, or use a smart pointer as ToohrVyk wrote):
    void create_something( CSomething*& something )    {        something = new CSomething();        something->x = 1;    }        int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )     {        CSomething* something;        create_something(something);        delete something;        return 0;    }

John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
A pointer to a reference?
Pointers to references aren't allowed by C++. References to pointers, which is what JohnBolton's code uses, are.

This topic is closed to new replies.

Advertisement