Advertisement

Return a reference?????

Started by June 13, 2002 03:57 AM
8 comments, last by the Chef 22 years, 5 months ago
If a function returns int* does a int* have to take it then? For examle:

int *myFunc() {
    int i;
    return i; // Returns the adress to i via a pointer huh?
}

int main() {
    int *i = myFunc(); // i will now have the adress to the local i huh?
}
  
But if we do the same thing with references, what happends then? for example:

int &myFunc() {
    int i;
    return i; // Whats returned now???
}

int main() {
    int i = myFunc(); // what will i be set to???
}
  
Thanks for all answers! [edited by - the Chef on June 13, 2002 4:58:55 AM]
No way! I will never write a profile signature! :p
dont get your code...

_________________________________________________________________________
Can someone be nice and help me on my way to be the next Hideo Kojima? Thought So...
Advertisement
quote: Original post by the Chef
int *myFunc() {    int i;    return i; // Returns the adress to i via a pointer huh?}int main() {    int *i = myFunc(); // i will now have the adress to the local i huh?} 



That won''t work. First of all, since a local variable is allocated on the stack, the memory is "free"-ed after the function returns. So if you return a pointer to it, you''ll be returning garbage. Secondly, your return statement won''t actually compile (because you''re trying to convert an int to an int *. You''d want something like return &i (assuming that i wasn''t a local variable.

Now, you can''t return a reference to a local variable, for the same reason I gave above. But assuming you return a non-local variable''s reference, the int i = myFunc(); line would simply copy the value of the return''ed integer into i. That is, it would work the same as if you simply returned an int.

codeka.com - Just click it.
quote: Original post by the Chef
int *myFunc() {
int i;
return i; // Returns the adress to i via a pointer huh?
}

No, this will not compile. There is no implicit conversion from int to int*. You would have to "return &i" to return the address of i (see below).
quote:
int main() {
int *i = myFunc(); // i will now have the adress to the local i huh?
}

Correct. i now points to the local variable within myFunc(). Since the local variable has gone out of scope, i really points at invalid storage. Don''t do this.

quote:
int &myFunc() {
int i;
return i; // Whats returned now???
}

You are now returning a reference to i. For arguments'' sake, this will be the same as the pointer but with a different syntax. You should not do this, since i is a local variable and will not exist at the point you "catch" the reference.
As has already been pointed out you should not return a reference or a pointer to a variable created locally in the function. Instead you'd have to create the variable dynamically in the function.

    int* myFunc() (    int* i = new int;    *i = 10;    return i;}int& myFunc2() {    int* i = new int;    *i = 10;    return *i;)    


I have to admit though, that I'm not 100% sure that the second one is safe, as I'm not entirely certain what happens when a reference to a variable on the heap goes out of scope. If only the reference goes out of scope, and not the 'real' variable, version 2 is leaky. Maybe someone else can shed some more light on this?

-Neophyte

-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GED d- s:+ a- C++$ UL++ P++ L++ E W+ N+ o K? w !O M--(+) V-- PS+
PE Y+ PGP t-- 5++ X+ R(+) rv+(++) b+++ DI+ D(+) G e+>++ h r--> y+
----- END GEEK CODE BLOCK-----
geekcode.com

EDIT: Forgot to initialize i

[edited by - Neophyte on June 13, 2002 8:16:43 AM]
quote:
If only the reference goes out of scope, and not the ''real'' variable, version 2 is leaky. Maybe someone else can shed some more light on this?


Yes, only the reference is deleted when it goes out of scope. Variables that has been created with new is never deallocated automatically. If you do not explicitly delete the int after you are done with it you will create a memoery leak. The style of programming you show here is often used in Java, since that language contains a garbage collector to clean this up for you.

Returning a newly allocated object to the caller is normally considered bad style since the caller easily might forget to delete it and thereby create a memory leak. Instead you should do like this:


  void myFunc2(int& i) {        i = 10;    )  


That way it is both the responsibility of the caller to both allocate and deallocate i and the risk of causing a memory leak will be reduced significantly. Of course, this style is harder to understand for the caller - but if you can''t live with that you are probably better of using Java.
Jacob Marner, M.Sc.Console Programmer, Deadline Games
Advertisement
IMHO, the only time that it''s really safe to return a reference to something is when you do something like:


  CObject& CObject::operator=(/*whatever*/){   // do stuff   return(*this);}  


or:


  string& CObject::operator[](int index){   // check bounds   return(someStringAtThatIndex);}  


Unless you know ahead of time that what you''re getting a reference to is either global or static, it seems to me that these are the only kinds of instances when you can be sure that the returned reference actually references something valid. Just my $0.02.

Other than these kinds of situations, when would one want to return a reference to something? This just seems to be asking for trouble.

/*=========================================*/
/* Chem0sh */
/* Lead Software Engineer & Tech Support */
/* http://www.eFaces.biz */
/*=========================================*/
/*=========================================// Chem0sh// Lead Software Engineer & Tech Support// http://www.eFaces.biz=========================================*/
Ideally, the ownership policy of the pointer should be made clear. This can be done using a smart pointer and, in this case, std::auto_ptr appears to have the correct semantics.

Example:

    #include <memory>#include <iostream>class C{public:	C() : val_()	{	}	explicit C(int val) : val_(val)	{		std::cout << "C()" << std::endl;	}	C(const C&)	{		std::cout << "copy C()" << std::endl;	}	~C()	{		std::cout << "~C()" << std::endl;	}	std::ostream& print(std::ostream& os) const	{		return os << val_ << std::endl;	}	typedef std::auto_ptr<C> ptr;private:	int val_;};C::ptr f(){	return new C(10);}int main(){	C::ptr pc = f();	pc->print(std::cout);}    


A "C" instance is created and a pointer to it returned by the function f(). The auto_ptr transfers ownership to the caller, and clean-up is automatically handled. The functions in class "C" demonstrate that there is only ever one instance of "C" created and destroyed, and that member functions are called as through a normal pointer.

[edited by - SabreMan on June 13, 2002 9:10:06 AM]
quote: Original post by Neophyte
    int* myFunc() (    int* i = new int;    *i = 10;    return i;}int& myFunc2() {    int* i = new int;    *i = 10;    return *i;)     

I understand the second funtion that returns a referense to the memory at *i, but the first one! The function is decalred like

int *myFunc()

but do it really have to??? i just keeps a adress and nothing else! Cant I return it as a value? Whats the difference?
Please help!
No way! I will never write a profile signature! :p
quote: Original post by the Chef
I understand the second funtion that returns a referense to the memory at *i, but the first one! The function is decalred like

int *myFunc()

but do it really have to??? i just keeps a adress and nothing else! Cant I return it as a value? Whats the difference?
Please help!


The difference is that an address is not always the same size as an int, when we start using those new intel IA64 machines, addresses will be 64-bit, but int''s may still be only 32-bit (though probably an int should become 64-bit at the same time, that''s not gauranteed)

so which you sometimes can return an address as an int, you probably shouldn''t. By the way, this is how you''d do it:

int *p = new *p( 100 );
int i = (int)p

printf( "i = %08X\n", i );
printf( "*(int *)i = %d\n", *(int *)i );


This would output something like:

001F02A5
100

(where the first number is an address, so it might be anything)

codeka.com - Just click it.

This topic is closed to new replies.

Advertisement