Is this reference declaration legal?

J

jl_post

Hi,

I've wondered for quite some time if it's legal to make a reference
to a pointer, like this:

void f()
{
SomeClass *ptr = new SomeClass;

SomeClass & ref = *ptr; // is this legal?

// Do stuff with ref here.

delete(ptr);
ptr = NULL;
return;
}

Ordinarily I'd say this is legal, but I haven't read any
documentation that explicitly says so.

(Now, I understand that it's bad form to allocate memory and free/
delete it in the very same scope, but I just want to know if it's okay
to declare a reference to a (de-referenced) pointer, assuming the
pointer points to a valid object and that the reference is not used
after the memory is freed/deleted.)

Thanks.

-- Jean-Luc
 
J

jl_post

Yes, certainly.


Thanks for your response, Victor, I appreciate it.


Because if it's all in the same scope, there's no need to declare
it as a pointer and allocate it memory. Just declare it on the stack
(as a non-pointer) and let it clean itself up.

This is described with more in detail at Bjarne Stroustrup's C++
Style and Technique FAQ at:

http://www.research.att.com/~bs/bs_faq2.html

under the question "Why isn't the destructor called at the end of
scope?"

Basically, what Stroustrup has to say about it is that "Code that
creates an object using new and then deletes it at the end of the same
scope is ugly, error-prone, and inefficient." While he uses
subjective language (like "ugly"), I happen to agree with him, for I
believe that memory that is allocated and freed/deleted in the same
scope has no reason not to be declared on the stack.

But if you feel I'm wrong about that, I'd like to hear your opinion
on the matter.

(Plus, I generally encourage C++ programmers to program with as few
pointers as possible. In my experience, about 90 to 95% of all
pointers I come across in C++ can easily be done away with by
replacing them with objects declared on the stack, std::strings,
std::vectors, and/or references.

And since about 95% of program crashes involve mis-handled pointer
memory (again, this is in my experience), eliminating most (if not
all) pointers in code will eliminate around 90% of crashes and
drastically improve correctness and, in my opinion, readability (as
code can now follow closer to pseudocode and not have as many
programming-language dependent extras like explicit memory frees).

Many C++ programmers don't realize that a lot of pointer handling
is unnecessary in C++ as C++ offers simple ways around most pointer
usage. So for these reasons I often challenge C++ programmers to
program without pointers. (Which, sadly, often ends in heated debates
where a programmer refuses to give up programming with pointers saying
it is impossible to do so. And when I show them it can be done, they
proclaim that they use pointers for efficiency, only to resent it when
I show them that the non-pointer solution is usually faster.
Thankfully, not all programmers are this way, but unfortunately some
are.))

Anyway, sorry for getting off-topic. And again, thanks for your
help, Victor.

Have a great week!

-- Jean-Luc
 
J

jl_post

That would require pretty big stack, for one. OTOH, if it's an array
you want whose size needs to be determined at run-time, you have no
other choice but to use dynamic memory. You have mechanisms that help
you like 'std::vector' or 'std::deque', or you can roll your own, but
those arrays aren't on the stack, that's for sure. And they allocate
their memory and free/delete it in the "very same scope", only without
actually exposing those operations.


You're right, of course. std::vectors and std::strings do use
pointers and memory allocation/deallocation under the hood, but that's
not what Bjarne Stroustrup (and I) want to avoid.

std::string and std::vectors (and other STL containers, I'm sure)
use memory allocation & deallocation, but they do so transparently, so
the programmer who uses them does not have to worry about it. The
containers are written so that they are self-cleaning (in that they
clean themselves when they go out of scope), relieving the programmer
who uses them of having to do any pointer maintenance on them.

When you use a pointer in the way that Stroustrup said you
shouldn't, like this:

void fct() // ugly, error-prone, and inefficient
{
X* p = new X;
// use p
delete p;
}

you have to:

a) remember to delete p at the end of the scope
b) remember to delete p if ever the function is prematurely exited
c) make sure p is never free()d (or deleted if malloc()ed)

and if you do allocate memory for a pointer that is meant to live
outside its scope, you still have to:

d) make it clear whose responsibility it is to free/delete the memory
e) make sure the memory really IS freed/deleted
f) make sure p is never deleted more than once

and if you are a programmer and are dealing with a buggy section of
code that uses a pointer, you still have these potential problems to
consider:

g) you may not necessarily know if the memory you're pointing to was
properly initialized
h) you may not necessarily know if the memory you're pointing to has
already been freed/deleted
i) you won't necessarily know if the pointer you have points to just
one instance of an object, or just the first element of an allocated
array of objects
j) if you have a pointer that you know points to the first element of
an allocated array of objects, you have no way of knowing when you go
out of the array bounds unless the original programmer was kind enough
to provide that information for you

(And for the record, I've seen ALL of these happen, and I've had to
fix all of them at least once.)

But if you use the alternatives C++ provides you (such as
std::strings, std::vectors, references, and declaring objects on the
stack), you'll never have to worry about those issues. For example,
if you avoid the manual memory allocation of an object (using new or
malloc()), you don't have to worry about double-freeing memory -- in
fact, you don't have to worry about de-allocating memory at all! STL
objects (declared on the stack) will do it for you so you don't have
to.

I encourage C++ programmers to avoid using the '*' operator in
their code (unless, of course, it's for multiplication). Doing so
avoids many headaches associated with pointers (like memory leaks and
crashes associated with pointers) as well as simplifies many aspects
of their code (like rarely having a need to write an operator=()
method or destructor for their classes).

Sure, the STL classes often use pointers "under the hood," but they
are used in STL classes transparently so that you don't have to
manipulate the pointers manually. When I encourage C++ programmers
not to use pointers, I don't mean not using classes and structures
that use pointers; I mean only using structures that are self-cleaning
-- and avoiding declaring pointers and manual allocation/deallocation
of memory.

Relying on objects declared on the stack (even if they are STL
containers) and not on manually allocated memory almost always results
in cleaner and less error-prone code. (And in many instances results
in faster, more efficient code as well.)

I hope this clarifies things, Victor.

Have a great weekend!

-- Jean-Luc
 

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

No members online now.

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,835
Latest member
KetoRushACVBuy

Latest Threads

Top