Returning a Reference
-
I've come across a situation where I don't understand entirely what's happening regarding references (not pointers). If we did this for example:
int someNumber = 5;
int& get()
{
return someNumber;
}void main()
{
int a = get(); //a = 5
get() = 52; //someNumber = 52
int b = get(); //b = 52, obviously
}We can change the value of some number by setting the return value of get() (or the long way around
int& ref = get(); ref = 52;
) But, in this case I'm not sure what exactly is going on:class bclass
{
public:
bclass(){}
virtual void cheese()=0;
bclass(const bclass& other){ _asm{int 3} }
};class dclass : public bclass
{
public:
dclass(){val=5;}
void cheese() { _asm{int 3} }
dclass(const dclass& other){ _asm{int 3} }int val;
};
dclass base;
bclass& get()
{
return base;
}void main()
{
dclass argh;
argh.val = 2;
get() = argh; //copy constructors not called, no error messages, base.val = 5
get().cheese();
}What happens when we try to set the return value of
get()
? Why doesn't anything happen? I also tried it with just references tobclass
so simply trying to set a reference to abclass
to a reference of a differentbclass
and still nothing. Also, before anybody says anything I'm not actually trying to set the return value to something else, or set any other variables in some bizarre manner it's just something I've come across quite by accident. EDIT: Or a much simpler example:bclass& argh = d2();
bclass& hmm = dclass();
hmm = argh;
hmm.cheese();Where dclass's implementation of cheese is called
My current favourite phrase: I've seen better!
-SK Genius
What you're trying to do is reassign the reference, which you can't do. It's a common mistake to make. What is actually occurring is the operator= is being called, but since you don't supply an implementation, it calls the compiler generated one. The compiler generated one essentially does nothing (EDIT: in this case). For primitive values, like in your first example, works like you would think because it's just transferring values. You can "reassign" the reference like this:
&get() = &argh;
"If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams
modified on Thursday, January 27, 2011 1:59 PM
-
What you're trying to do is reassign the reference, which you can't do. It's a common mistake to make. What is actually occurring is the operator= is being called, but since you don't supply an implementation, it calls the compiler generated one. The compiler generated one essentially does nothing (EDIT: in this case). For primitive values, like in your first example, works like you would think because it's just transferring values. You can "reassign" the reference like this:
&get() = &argh;
"If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams
modified on Thursday, January 27, 2011 1:59 PM
&get() = &argh ... I understand what you mean but ... is that legal C++ or just a hack around a (sort of) compiler bug? There is nothing like that in the c++ reference book!
2 bugs found. > recompile ... 65534 bugs found. :doh:
-
I've come across a situation where I don't understand entirely what's happening regarding references (not pointers). If we did this for example:
int someNumber = 5;
int& get()
{
return someNumber;
}void main()
{
int a = get(); //a = 5
get() = 52; //someNumber = 52
int b = get(); //b = 52, obviously
}We can change the value of some number by setting the return value of get() (or the long way around
int& ref = get(); ref = 52;
) But, in this case I'm not sure what exactly is going on:class bclass
{
public:
bclass(){}
virtual void cheese()=0;
bclass(const bclass& other){ _asm{int 3} }
};class dclass : public bclass
{
public:
dclass(){val=5;}
void cheese() { _asm{int 3} }
dclass(const dclass& other){ _asm{int 3} }int val;
};
dclass base;
bclass& get()
{
return base;
}void main()
{
dclass argh;
argh.val = 2;
get() = argh; //copy constructors not called, no error messages, base.val = 5
get().cheese();
}What happens when we try to set the return value of
get()
? Why doesn't anything happen? I also tried it with just references tobclass
so simply trying to set a reference to abclass
to a reference of a differentbclass
and still nothing. Also, before anybody says anything I'm not actually trying to set the return value to something else, or set any other variables in some bizarre manner it's just something I've come across quite by accident. EDIT: Or a much simpler example:bclass& argh = d2();
bclass& hmm = dclass();
hmm = argh;
hmm.cheese();Where dclass's implementation of cheese is called
My current favourite phrase: I've seen better!
-SK Genius
get() = argh;
callsbclass::operator=
which doesn't exist*. Even if it did exist, val is not a member of bclass and thus couldn't be copied anyway. If you define the return type of get() as dclass&, and in addtion to that define the assignment operator for this class, then it might work. P.S.: to my knowledge assignment operators can't be made virtual, but you might be able to get this to work with a trick like this:class base {
virtual void assign(const base& other)=0; //<- helper function
public:
base& operator=(const base& other) { assign(other); return *this; }
};
class derived : public base {
virtual void assign(const base& other) {
const derived* pOther = &(dynamic_cast<const derived&>(other));
if (pOther != 0) {
val = pOther->val;
}
}
public:
derived() : val(5) {}
int val;
};
derived myglobalderived; // val is initialized to 5
derived& get() { return myglobalderived; }
void test() {
derived mylocalderived;
mylocalderived.val = 3;
get() = mylocalderived;
std::cout << "get() = " << get().val;
}*P.P.S: while bclass::operator= hasn't been defined explicitely, the compiler might create one automatically (but it wouldn't make any difference as explained above). I am not sure in this case however, since assignment operators can't be virtual, and bclass is an abstract class. A member-wise copy will not make any sense, as you can't create instances for an abstract class, and derived classes will overwrite, not override the assignment operator.
modified on Thursday, January 27, 2011 5:58 AM
-
What you're trying to do is reassign the reference, which you can't do. It's a common mistake to make. What is actually occurring is the operator= is being called, but since you don't supply an implementation, it calls the compiler generated one. The compiler generated one essentially does nothing (EDIT: in this case). For primitive values, like in your first example, works like you would think because it's just transferring values. You can "reassign" the reference like this:
&get() = &argh;
"If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams
modified on Thursday, January 27, 2011 1:59 PM
-
ahmed zahmed wrote:
The compiler generated one essentially does nothing.
It does copy all members of the class by using each members assignment operator, default or explicitly declared and implemented.
Since bclass's oeprators are being called, only members of bclass are being copied, i. e. nothing. See my edit on my previous response.
-
Since bclass's oeprators are being called, only members of bclass are being copied, i. e. nothing. See my edit on my previous response.
-
It was more of a clarification of what seemed to be a general statement that could be interpreted as "a default assignment operator does nothing".
I see. I didn't read it as a general statement, but I now recognize it might be considered as such. Good point.
-
&get() = &argh ... I understand what you mean but ... is that legal C++ or just a hack around a (sort of) compiler bug? There is nothing like that in the c++ reference book!
2 bugs found. > recompile ... 65534 bugs found. :doh:
Just to clear up some of the confusion: To the compiler, a reference is equivalent to a pointer in everything but the method of dereferencing. It treats the reference as a pointer to a memory location that occupies the contents of some variable. To the programmer, a reference is equivalent to an alias. Through that reference you can manipulate the contents of another variable without knowing it's orginal name, by using an alternate name. Your method get() effectively returns a temporary alternate alias to your globale variable. You can assign this to a variable of type reference to bclass (bclass&) in order to use that variable as an alias to your global variable, or, like you did, you can just use the temporary alias immediately. ahmed's suggestion was that you can reassign the alias to another variable, in this case the local variable argh. But it wouldn't work as the address of operator itself is not a reference, and therefore
get()
is not an l-value. Reassigning a variable of type reference to another variable is not possible. -
ahmed zahmed wrote:
The compiler generated one essentially does nothing.
It does copy all members of the class by using each members assignment operator, default or explicitly declared and implemented.
You do make a good point, so I edited my response to clarify. Thanks for keeping me honest.
"If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams
-
&get() = &argh ... I understand what you mean but ... is that legal C++ or just a hack around a (sort of) compiler bug? There is nothing like that in the c++ reference book!
2 bugs found. > recompile ... 65534 bugs found. :doh:
no, it's not legal, it was just an attempt to clarify what he was attempting to do.
"If your actions inspire others to dream more, learn more, do more and become more, you are a leader." - John Quincy Adams