Returning reference to pointer

H

Haquejiel

Hello. I have a question that is simultaneously simple and
complicated.
I have a custom class I wrote, and I want to return new instances of
it by reference (for odd reasons). I have the deconstructor of this
class outputting to stdout when it is called.

In MSVC++, returning a reference to a new instance of this object
seems to be legitimate - if I assign it to a local reference, it gets
deconstructed when it goes out of scope - but does it get deleted?

Here's an example of what I've been testing against:

Object& someFunction()
{
Object *newObject = new Object();
return *(newObject);
}

int main()
{
Object outer = someFunction();
cout << "Before" << endl;
{
Object inner = someFunction();
}
cout << "After" << endl;
return 0;
}

The result of this appears to be as such (pretending the deconstructor
outputs the object name):

Before
inner deconstructed.
After
outer deconstructed.

If I do not assign someFunction() to a value, a deconstructor is never
apparently called. Is this a memory leak?
The deconstructor is being called for inner, but is the memory getting
cleaned up?

These are pretty specific questions, but I'm having trouble finding
them answered explicitly. Could anyone help me out here? :)

Thankee
- (e-mail address removed)
 
K

Kai-Uwe Bux

Haquejiel said:
Hello. I have a question that is simultaneously simple and
complicated.
I have a custom class I wrote, and I want to return new instances of
it by reference (for odd reasons). I have the deconstructor of this
class outputting to stdout when it is called.

In MSVC++, returning a reference to a new instance of this object
seems to be legitimate - if I assign it to a local reference,

In the code below, you are not assigning to local references. You initialize
local object from the returned reference. If you want to hold references to
the allocated object, you should do:

Object & outer = someFunction();
Object & inner = someFunction();

it gets
deconstructed when it goes out of scope - but does it get deleted?

The objects allocated in someFunction are never deleted in your code. That
is a memory leak. (Note that "delete" does not appear anywhere in the
code.)

Here's an example of what I've been testing against:

Object& someFunction()
{
Object *newObject = new Object();
return *(newObject);
}

int main()
{
Object outer = someFunction();
cout << "Before" << endl;
{
Object inner = someFunction();
}
cout << "After" << endl;
return 0;
}

The result of this appears to be as such (pretending the deconstructor
outputs the object name):

Before
inner deconstructed.
After
outer deconstructed.

If I do not assign someFunction() to a value, a deconstructor is never
apparently called. Is this a memory leak?
The deconstructor is being called for inner, but is the memory getting
cleaned up?

The destructor is called for the object "inner", which is not the same
object as allocated by the someFunction() call.

[snip]


Best

Kai-Uwe Bux
 
H

Haquejiel

Haquejiel said:
Hello. I have a question that is simultaneously simple and
complicated.
I have a custom class I wrote, and I want to return new instances of
it by reference (for odd reasons). I have the deconstructor of this
class outputting to stdout when it is called.
In MSVC++, returning a reference to a new instance of this object
seems to be legitimate - if I assign it to a local reference,

In the code below, you are not assigning to local references. You initialize
local object from the returned reference. If you want to hold references to
the allocated object, you should do:

Object & outer = someFunction();
Object & inner = someFunction();
it gets
deconstructed when it goes out of scope - but does it get deleted?

The objects allocated in someFunction are never deleted in your code. That
is a memory leak. (Note that "delete" does not appear anywhere in the
code.)


Here's an example of what I've been testing against:
Object& someFunction()
{
Object *newObject = new Object();
return *(newObject);
}
int main()
{
Object outer = someFunction();
cout << "Before" << endl;
{
Object inner = someFunction();
}
cout << "After" << endl;
return 0;
}
The result of this appears to be as such (pretending the deconstructor
outputs the object name):
Before
inner deconstructed.
After
outer deconstructed.
If I do not assign someFunction() to a value, a deconstructor is never
apparently called. Is this a memory leak?
The deconstructor is being called for inner, but is the memory getting
cleaned up?

The destructor is called for the object "inner", which is not the same
object as allocated by the someFunction() call.

[snip]

Best

Kai-Uwe Bux

Alright. Thank you very much for the prompt response. That answers my
questions. Sorry for the semantic issue on the local reference bit (I
did not meant a C++ reference - some ambiguity there).

I was unsure of if the value was getting deleted or not, and the
deconstruction was throwing me off a bit.

Thank you :)

- (e-mail address removed)
 
J

jason.cipriani

I was unsure of if the value was getting deleted or not, and the
deconstruction was throwing me off a bit.

This doesn't deal with your problem specifically but I've been in
similar situations. One technique I've found useful for these kinds of
things is printing the value of 'this' in your debugging statements:

struct Object {
Object (void) { cout << this << ": constructed" << endl; }
~Object (void) { cout << this << ": destructed" << endl; }
};


Object& someFunction()
{
cout << "someFunction entered" << endl;
Object *newObject = new Object();
cout << "someFunction returning" << endl;
return *(newObject);
}

int main()
{
Object outer = someFunction();
cout << "Before" << endl;
{
Object inner = someFunction();
}
cout << "After" << endl;
return 0;

}

Prints something like this:

someFunction entered
0x3d4fa8: constructed
someFunction returning
Before
someFunction entered
0x3d4fc8: constructed
someFunction returning
0x22ff40: destructed
After
0x22ff50: destructed

And shows that the ones destroyed aren't the same as the ones you
created.

Jason
 
H

Haquejiel

This doesn't deal with your problem specifically but I've been in
similar situations. One technique I've found useful for these kinds of
things is printing the value of 'this' in your debugging statements:

struct Object {
Object (void) { cout << this << ": constructed" << endl; }
~Object (void) { cout << this << ": destructed" << endl; }

};

Object& someFunction()
{
cout << "someFunction entered" << endl;
Object *newObject = new Object();
cout << "someFunction returning" << endl;
return *(newObject);

}

int main()
{
Object outer = someFunction();
cout << "Before" << endl;
{
Object inner = someFunction();
}
cout << "After" << endl;
return 0;

}

Prints something like this:

someFunction entered
0x3d4fa8: constructed
someFunction returning
Before
someFunction entered
0x3d4fc8: constructed
someFunction returning
0x22ff40: destructed
After
0x22ff50: destructed

And shows that the ones destroyed aren't the same as the ones you
created.

Jason

Thank you. I was actually in the process of implementing that very
idea when I decided to check on here to see if anyone had anything to
say. I have to say that I still find reference/instance/pointer
differences in cases like this a bit ambiguous in online tutorials/
documentation. The C++ FAQ Lite has been exceedingly useful, however.

Are there any references you'd strongly recommend I look into?

Thank you,

(e-mail address removed)
 
J

jason.cipriani

Haquejiel said:
Are there any references you'd strongly recommend I look into?

Well if you are asking me *personally*... I'm probably the wrong guy
to ask (as an American, I generally take the approach of doing nothing
until something really bad happens, then severely overcompensating
later; so I don't know many references). This stuff confuses the heck
out of me, too. This newsgroup is a great reference, of course, and
that FAQ (I keep a local copy on my machine). I've also found
Stroustrup's "The C++ Programming Language" book to be a really
enlightening reference (in fact, that is one of only 3 technical books
that I own).

For some issues, some of it is just a matter of experience and
familiarity with certain concepts. For example, once you know the
difference between things like:

A &a = AnotherA; // binds a reference
A *a = &AnotherA; // stores address
A a = AnotherA; // makes a copy
A a(AnotherA); // another way to copy

You don't really forget, and then other things kind of fall into
place. I'm a big fan of taking a few minutes during down time to sit
down and experiment with stuff. I wouldn't mind if somebody pointed
out some good reference material as well.

Jason
 
J

James Kanze

This doesn't deal with your problem specifically but I've been
in similar situations. One technique I've found useful for
these kinds of things is printing the value of 'this' in your
debugging statements:
struct Object {
Object (void) { cout << this << ": constructed" << endl; }
~Object (void) { cout << this << ": destructed" << endl; }

};

Also, when you do this, be sure to either inhibit copy and
assignment, or provide instrumented versions of those as well.
Had the OP instrumented copy as well, he would have seen
immediately what was happening.

(I've not got it in my library yet, but on occasion, I've used a
macro along the lines of:

#define instrument( f ) \
std::cerr << # f << ": " << this << std::endl

Saves a little bit if typing:). And in large projects, of
course, every function will be instrumented anyway, using the
project's standard logging mechanism.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top