Archived

This topic is now archived and is closed to further replies.

alnite

empty references

Recommended Posts

I tried to put an empty reference in C++ just like in Java or C#.
class Foo
{
   MyClass&  otherClass;

public:
   void SetMyClass( MyClass& other )
   {
      otherClass = other;
   }
}; 
But then the compiler gives me an error saying that I have to initialize otherClass in the ctor. But I don't want to initialize it in ctor. Even if I wanted to, how do I initialize it? otherClass is supposed to be referencing an object outside, it's not supposed to be instantiated. I tried to create a ctor that accepts MyClass& argument, it still gives me the error. The compiler expects it to be initialized in the initializer list. Any help please? [edited by - alnite on November 14, 2003 12:10:56 PM]

Share this post


Link to post
Share on other sites
If for some reason you cannot initialise the reference at the point of the object's construction, or what to change what it is bound to, use a pointer (MyClass*) instead. You cannot change what a reference is bound to, yet you can assign a new address to a pointer.

[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || CUJ || MSVC++ Library Fixes || BarrysWorld || E-Mail Me ]

[edited by - Lektrix on November 14, 2003 12:14:37 PM]

Share this post


Link to post
Share on other sites
Oh goody! A question I might be able to answer! References in C++ are not a replacement for pointers. A reference always has to refer to something that actually exists, from the time of initialization, to it’s end. That means you have to initialize a reference to some object.

If ever a reference can point to nothing, it’s a sure sign you need a pointer instead. Pointers can point to null, or random garbage if you want. I suppose you could initialize the reference to a dummy value. But I wouldn’t.

[edit]
Bah! Lektrix! Trust someone to beat me to it with a concise and yet complete answer. :/
[/edit]

[edit]
Actually, a concise, complete, but not entirely correct answer:
quote:

You cannot change what a reference is bound to...


[edit]
Here is an example of Nonsense: (See posts below for comments)
[/edit]

int int1 = 0;
int int2 = 1;
int &refint = int1;

refint = int1;
refint = int2;
refint = int1;
refint = int2;
// etc.


Are you thinking of const references?

const int &const_refint = int1;
const_refint = int2; // The compiler won't like this. Assigning to a const l-value indeed!


[/edit]

Ro_Akira

P.S. Edits eat "source" tags for breakfast.

[edited by - Ro_Akira on November 14, 2003 12:13:17 PM]

[edited by - Ro_Akira on November 14, 2003 12:20:02 PM]

[edited by - Ro_Akira on November 14, 2003 12:34:01 PM][/source]

[edited by - Ro_Akira on November 14, 2003 12:35:24 PM]

[edited by - Ro_Akira on November 14, 2003 12:36:18 PM]

[edited by - Ro_Akira on November 14, 2003 1:03:24 PM]

Share this post


Link to post
Share on other sites
Hi alnite.

Section 8.3.2 paragraph 4 of the C++ standard states :

quote:

The decla-ration of a reference shall contain an initializer (8.5.3) except when the declaration contains an explicit
extern specifier (7.1.1), is a class member (9.2) declaration within a class declaration, or is the declara-tion
of a parameter or a return type (8.3.5); see 3.1. A reference shall be initialized to refer to a valid object
or function. [Note: in particular, a null reference cannot exist in a well-defined program, because the only
way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer,
which causes undefined behavior. As described in 9.6, a reference cannot be bound directly to a bit-field. ]



So in short, you need to initialize it. The only way you can initialize it when it is a class member is through the initializer list, so your stuck with it .

Share this post


Link to post
Share on other sites
Or maybe I could write a pointer_reference class, a class that can be used both as a pointer and a reference...something like smart pointers, except that it doesn''t delete the pointer.

Oh wait, I can''t overload . (dot) dang it!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Well if you dont like -> you could always just not use it

pclass->member or
*pclass.member

But i think -> looks a lot better

Share this post


Link to post
Share on other sites
something i have never understood about references, i have always seen everyone say a reference cannot point to null, it always has to point to an object


so what happens in this case if there is no memory to allocate?

MyClass & obj = new(std::nothrow) MyClass;

?

Share this post


Link to post
Share on other sites
quote:

Well if you dont like -> you could always just not use it

pclass->member or
*pclass.member

But i think -> looks a lot better



Actually, it's worse than that. My compiler at least, MSVC++ 6.0 SP5, likes (*pclass).member. And it's quite right too. Consider *pclass.myint = 5; This is really *(pclass.myint) = 5; That's assigning 5 to the deferenced pointer pclass.myint. "But pclass.myint isn't a pointer!" - compiler.

quote:

something i have never understood about references, i have always seen everyone say a reference cannot point to null, it always has to point to an object


so what happens in this case if there is no memory to allocate?

MyClass & obj = new(std::nothrow) MyClass;



I'm putting a bet on "Crash".

Consider also:


int &myclass::returnint ()
{
return *pint; // pint is a pointer to an int. If it's pointing to null, or some other God forsaken place...

}

Ro_Akira

[edited by - Ro_Akira on November 14, 2003 12:30:16 PM]

Share this post


Link to post
Share on other sites
Original post by Ro_Akira
quote:

You cannot change what a reference is bound to...


Nonsense.

int int1 = 0;
int int2 = 1;
int &refint = int1;

refint = int1;
refint = int2;
refint = int1;
refint = int2;
// etc.




ummm, surely that is just assigning the value, not changing what the reference refers to..

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by necromancer_df
<blockquote>Original post by Ro_Akira
quote:

You cannot change what a reference is bound to...


Nonsense.

int int1 = 0;
int int2 = 1;
int &refint = int1;

refint = int1;
refint = int2;
refint = int1;
refint = int2;
// etc.


</blockquote>

ummm, surely that is just assigning the value, not changing what the reference refers to..




Havnt you just contradicted yourself there? You arnt changing what the reference is bound to, your changing the value of the object the reference is bound to.

Share this post


Link to post
Share on other sites
quote:
Original post by Ro_Akira
quote:

something i have never understood about references, i have always seen everyone say a reference cannot point to null, it always has to point to an object


so what happens in this case if there is no memory to allocate?

MyClass & obj = new(std::nothrow) MyClass;



I''m putting a bet on "Crash".

Consider also:


int &myclass::returnint ()
{
return *pint; // pint is a pointer to an int. If it''s pointing to null, or some other God forsaken place...
}

Ro_Akira





okay i got curious and tested this in VC .NET

seems it treats references and pointers identically, in both cases it doesnt crash until the reference is read from or assigned to.

so in effect the only difference between the 2 is that the reference cant be changed after initilisation and the syntax to use them

Share this post


Link to post
Share on other sites
quote:

ummm, surely that is just assigning the value, not changing what the reference refers to..



What I meant to say was, "Here is an example of nonsense:", instead of "Nonsense".

You''re all right of course.

Ro_Akira

Share this post


Link to post
Share on other sites
quote:
Original post by Ro_Akira
Actually, a concise, complete, but not entirely correct answer:
quote:

You cannot change what a reference is bound to...


Nonsense.

int int1 = 0;
int int2 = 1;
int &refint = int1;

refint = int1;
refint = int2;
refint = int1;
refint = int2;
// etc.

Are you thinking of const references?

const int &const_refint = int1;
const_refint = int2; // The compiler won''t like this. Assigning to a const l-value indeed!



That is not nonsense. What you''re saying is nonsense. You are merely assigning to the object that refint refers to, not binding the reference to another object.

[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || CUJ || MSVC++ Library Fixes || BarrysWorld || E-Mail Me ]

Share this post


Link to post
Share on other sites
quote:

okay i got curious and tested this in VC .NET

seems it treats references and pointers identically, in both cases it doesnt crash until the reference is read from or assigned to.

so in effect the only difference between the 2 is that the reference cant be changed after initilisation and the syntax to use them



Yeah, I probably should have said crashed eventually. I think it's reasonable to assume that a reference will be at least read after either of the two examples though, and the end result will be a crash.

quote:

...What you're saying is nonsense...



I apologise. That's what I get for thinking "It compiles, so I must right!". Ha!

Ro_Akira

[edited by - Ro_Akira on November 14, 2003 1:13:05 PM]

[edited by - Ro_Akira on November 14, 2003 1:13:39 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
narcist wrote:

something i have never understood about references, i have always seen everyone say a reference cannot point to null, it always has to point to an object


so what happens in this case if there is no memory to allocate?

MyClass & obj = new(std::nothrow) MyClass;

i''m writing:

so actually, you can do this. it''s not a good idea. you can also do this:

MyClass& obj = *((MyClass*)NULL);

(hope i have the syntax right)

i knew a guy who did that in the project that we were on. he probably got the idea from Scott McNeally (don''t know if that''s the right name)''s book Effective C++. i think you can do this because c++ implements references as pointers with a bunch of compile time stuff around them...

however -- the Effective C++ book goes on to say that this is horrible software design and should not be done, because the whole idea of references (or at least a major part of them) is they remove the "check for NULL" hassle/danger/requirement of pointers, and you''re invalidating that by doing this...

so don''t do it.


Share this post


Link to post
Share on other sites
I should probably have thought about this before answering (see above posts), but...

quote:

MyClass& obj = *((MyClass*)NULL);

I knew a guy who did that in the project that we were on. he probably got the idea from Scott McNeally (don't know if that's the right name)'s book Effective C++. i think you can do this because c++ implements references as pointers with a bunch of compile time stuff around them...



I'm blind as to how I can use this for anything. Any reading or writing will be to no-mans-land. And you can't bind it to anything else like a real instance of MyClass, as Lektrix, no less, pointed out!

[edit]
I have Effective C++ Second Edition in my possession (despite appearances to the contarary (see above posts!)). Can you say in which item he talks about it?
[/edit]

Ro_Akira

[edited by - Ro_Akira on November 14, 2003 1:30:21 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
MyClass& obj = *((MyClass*)NULL);

(hope i have the syntax right)

i knew a guy who did that in the project that we were on. he probably got the idea from Scott McNeally (don''t know if that''s the right name)''s book Effective C++. i think you can do this because c++ implements references as pointers with a bunch of compile time stuff around them...



I think you are referring to More Effective C++, page 10, by Scott Meyers. He says

quote:

char *pc =0;
char& rc = *pc;

Well, this is evil, pure and simple. The results are undefined..



He does make clear that this is undefined behaviour, and is using the example as a way to prove that you cannot have null references. This is explicitly stated in the standard ( i did quote it above but here is the relevant part)

quote:

A reference shall be initialized to refer to a valid object
or function. [Note: in particular, a null reference cannot exist in a well-defined program, because the only
way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer,
which causes undefined behavior.


Share this post


Link to post
Share on other sites
quote:
Original post by Narcist
something i have never understood about references, i have always seen everyone say a reference cannot point to null, it always has to point to an object



It's not supposed to be null, and I think a program that allows it to be null is ill-formed, but like many things that are not supposed to happen, they still actually can.

void pathological_example(const int i);
int* j=0;
pathological_example(*j);

...
quote:
AP
i think you can do this because c++ implements references as pointers with a bunch of compile time stuff around them...


All languages implement references using pointers, it's the only way it can possibly work for the general case. As an optimization, when the data is small and is not mutated by the called function, the pointer can be eliminated and replaced by stack or register parameters (such as for integers or floating-point parameters).

[edited by - Magmai Kai Holmlor on November 14, 2003 4:39:50 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Narcist
okay i got curious and tested this in VC .NET

seems it treats references and pointers identically, in both cases it doesnt crash until the reference is read from or assigned to.

so in effect the only difference between the 2 is that the reference cant be changed after initilisation and the syntax to use them



That is only under an MSVC debug build. The behavior is undefined, which means it might crash or it might not. It might even format your hard-drive - we have no idea what it will do. It could even work, but there is no guarantee that it will.

Share this post


Link to post
Share on other sites
The OP also asked how to do it as an initialisation, and I don''t think anyone told them...

class Foo{
MyClass& otherClass;
public:
void SetMyClass( MyClass& other ) : otherClass(other) {}
};

That initialises otherClass with the object other. Hope that helps .

Share this post


Link to post
Share on other sites