JOIN
Get Time
forums   
Search | Watch Thread  |  My Post History  |  My Watches  |  User Settings
View: Flat (newest first)  | Threaded  | Tree
Previous Thread  |  Next Thread
Part 2 | Reply
Why not use references as means to reduce typing? (Googled "reference spree" but didn't find any Bad Thing reference.) I do that quite often; I think it's appropriate enough and might even be helpful in learning C++ references mindset - "I mean the same object, yeah, regardless of whether I'll get implemented as a pointer behind the scenes or hopefully more efficiently inferred, just the same object!" - by showing how they're more general than just clumsier pointers or just syntax for in-out function arguments. I also get the feeling that doing so may help the compiler eliminate common subexpressions; not checked.
Re: Part 2 (response to post by ulzha) | Reply
I agree. Using references wherever it makes the code more readable is a good thing. We shouldn't we worrying about having too many references.

Also, you can have a NULL reference.
Re: Part 2 (response to post by d000hg) | Reply
Also, you can have a NULL reference.

Would you care to elaborate?
Re: Part 2 (response to post by Krzysan) | Reply
It's fairly easy to have a null reference. g++ compiles this:

#include <cassert>
int main() {
    int *j = NULL;
    int & i = *j;
    assert(&i==NULL);
    return 0;
}
Re: Part 2 (response to post by eraserhd) | Reply
It's fairly easy to have a null reference.

It's fairly easy to shoot oneself in the foot as well ;-)

The standard (section 8.3.2.4) is pretty clear on that:

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.


Edit: I was quite surprised to see this program not to stackdump. Inspecting assembly showed that g++ optimized i away (along with dereferencing j) and simply compared j to NULL in the assert.
Re: Part 2 (response to post by Krzysan) | Reply
Well, this is clearly bad form, and having null references defeats the whole point of them in the first place. In terms of programming practices and the excerpt from the standard, yes this is "undefined."

But I'm pretty sure what happens when I dereference a null pointer, too, and that's not defined, because I know how my machine works. I think this is the same thing. The kind of machinery that would be needed to validate a program to prevent this during compilation has been tried, and it's a really hard problem and not really "the C++ way."

So it's safe to assume that null references work, although doing them intentionally in code that isn't disposable should result in the coder's public humiliation.
Re: Part 2 (response to post by ulzha) | Reply
"using references having in mind just the reason of reduced typing would lead you to a "reference spree" ". I coined the term "reference spree" (i have not found it in any books), so i guess it won't appear in a google search. Why did i say that? Because i think that shouldn't be the reason to use references. I would say that anybody doing that has not a clear concept in his mind about what references do mean in C++. You should use references in accordace with the purposes the language introduced them for. Indeed they tend sometimes to reduce typing but that's a side effect and not the reason one should use them.
Re: Part 2 (response to post by eraserhd) | Reply
If such corner cases do not brake your programme, it means your compiler is smart as Krzysan proved it. It does not mean what you wrote it's correct (from a behavioral point of view).
Re: Part 2 (response to post by zmij) | Reply
True, but it's a common situation where you create a reference by dereferencing a pointer. You can argue it's not good form, but C++ is rarely a model of good OO by its very nature.
Re: Part 2 (response to post by d000hg) | Reply
It depends how you look at it. One could argue (I would) that you cannot really create a NULL reference because by the time assignment should occur the program has already blown up due to NULL pointer dereferencing.

Programming language is not only syntax. There's meaning (semantics) assigned to that syntax. If the language specification says that certain constructions, even though syntactically correct, will not have meaning (are semantically incorrect), then they do not belong to the language. Hence NULL references do not belong to C++.
Re: Part 2 (response to post by Krzysan) | Reply

It depends how you look at it. One could argue (I would) that you cannot really create a NULL reference because by the time assignment should occur the program has already blown up due to NULL pointer dereferencing.

I know you did some amazing things with assembly in MM18, so that's why you saying this strikes such a strange chord.

How exactly would the compiler's code "dereference" it if I've not instructed the compiler to do anything with the contents of that memory location (neither read nor write)? The right-hand side of:
  int & i = *j;

Is an lvalue evaluated as an address expression. It's undefined, sure, but no less likely to work than:
struct Foo {
  int bar;
};
int main() {
  printf("%d\n", sizeof(((Foo*)NULL)->bar));
}


which is also technically undefined.
Re: Part 2 (response to post by eraserhd) | Reply
In MM18 I didn't do any assembly, I did some low-level C++ optimizations.

References do not have to be implemented as pointers, so right-hand side of that expression doesn't have to be address expression. But you're right, most if not all implementations work this way. Note that if you don't use i, implementations are allowed (and do) optimize i away and no NULL reference is actually created.

"Blown up" meant here "left the scope of valid C++". As your examples show, that doesn't have to lead any immediate consequences.
Re: Part 2 (response to post by Krzysan) | Reply
A very common usage that I've seen is when a method argument list contains a reference, and the calling code passes a dereferenced pointer.

Our practice is to require the calling code to ensure that the pointer is not NULL, prior to passing its dereferenced value into the method.

If we're passing a pointer into a method, we require the called method to check for a NULL pointer.

This reflects our practice of specifying a reference in the argument list when an argument MUST exist, and to specify a pointer if it MAY exist.
RSS