
Why should I use a pointer rather than the object itself? - olouv
http://stackoverflow.com/questions/22146094/why-should-i-use-a-pointer-rather-than-the-object-itself?newsletter=1&nlcode=47931%7c9e27
======
stormbrew
> note: in java, everything(except basic types) is a pointer. so you rather
> should ask the opposite: why do I need simple objects?

I think this is by far the most important piece of advice in that thread. It
gets right to the heart of one of the most basic areas of confusion that
programmers coming from garbage collected environments to ones with manual
memory management have.

They need to understand that they have NOT been working in an environment
_without pointers_ , as they are often told to believe, but one in which
_nearly everything is a pointer_. Understanding this is fundamental to
understanding these differences and a 10,000 word essay about C++ allocation
policies will not make it any clearer without dealing with that first.

~~~
banachtarski
I'm amazed at how many new programmers enter the workforce without a basic
understanding of the stack and the heap.

~~~
greatdox
Most of them are recent high school and college dropouts. What did you expect
them to know?

They learned programming by reading blogs and pirated PDF files on BitTorrent.
Of course they don't got a level of understanding most hackers here have.

You want a good programmer you need 15+ years of experience plus a good
understanding of computer science, recent high school and college dropouts
don't have that.

You hire a cheaper labor source, you won't get that level of quality a more
expensive labor source will give you and you get what you pay for!

~~~
banachtarski
Well, to be fair, I don't have 15 years of experience (professional experience
anyways). But I do believe the fundamentals are important and they seem to be
glossed over.

------
GuiA
Related Stack Overflow question: "C++: Why should `new` be used as little as
possible?"

[https://stackoverflow.com/questions/6500313/c-why-should-
new...](https://stackoverflow.com/questions/6500313/c-why-should-new-be-used-
as-little-as-possible)

~~~
gd1
There are some very good answers to that question. Related to that question, I
still fail to see any advantage to using shared_ptr, weak_ptr, unique_ptr,
auto_ptr, etc. If you are doing C++ right, nearly everything should be
allocated on the stack, and the things that aren't should be encapsulated in a
class, RAII style. If you can't design your program so that the ownership and
lifetime of your objects are clear, then you're using the wrong language, and
shared_ptr won't save you.

~~~
srean
The word RAII by itself is too non-specific. People typically mean: use (i) a
scoped/auto pointer or (ii) a shared pointer (thats C++ speak for reference
counted pointers). These are good thumb rules to rely on, but in itself they
are very inadequate.

First, auto or scoped pointer gets you a stack discipline. If your objects
weren't very big, you might as well create them on the stack itself. More
efficient and suitable for multithreading. If the lifetime does not follow the
lexical stack then you are out of luck with this style of RAII.

Next, reference counted pointers: Cycles are clearly a problem. The
traditional mantra is: use weak pointers to break cycles, but then you are
back to error prone manual management (of cycles). If I am to be trusted with
using weak pointers correctly, I wouldn't be too bad with manual memory
management either. Pure functional languages with eager semantics do not allow
cycles, so are ref counts a good idea in such cases ?

Although, many do not think about it that way, reference counted system is a
_garbage_collector_. Just a particularly simple one. Just because one
understands how it works, does not disqualify it from being a garbage
collection system. It is just not a very efficient garbage collector for cases
where running time is sensitive to cache locality, which is true fairly often.

I am quite excited about Rust's regions. I dont think programming with regions
is easy and you would want to have a garbage collector anyway. I hope this
style of programming sees more mainstream visibility. Something should come
out of all the MLton work on this. EDIT Indeed meant MLKit but it draws enough
from MLton that I thought HNers would be able to relate.

There is also D's scoped guards, but I am not yet familiar with what they do.

~~~
sixbrx
[Regarding Rust:] > I dont think programming with regions is easy and you
would want to have a garbage collector anyway.

I agree and I've been wanting to emphasize this too for a while.

I think it would help Rusts adoption a lot if it would get a good garbage
collector while it's still young. Otherwise I think a lot of programmers will
give up after stumbling around with borrow-checker errors when doing some
things that are pretty trivial in other languages.

If we had a garbage collector, we could only worry about regions in the hot
spots, that would ease many people's way into the language a lot, IMO.

~~~
stormbrew
I actually think the moves Rust has made away from an expectation of GC as
part of the language will only help its adoption down the road. There are
about 8 billion languages occupying some facet of the C++ With Garbage
Collector niche and we don't really need another one. We need a better C++,
and it's not a better C++ if you can't use it without a garbage collector,
it's just another Java/D/Go/so on and on and on.

~~~
sixbrx
I agree it should be usable without a garbage collector, for sure.

But some types of algorithms which are allocation heavy (with dynamically
sized parts) will just run much faster with a good collector, and are easier
to write that way.

Also I've found that with regions, things get really complicated when
structures contain borrows (and not every structure will logically own what it
references), and then the structures become parameterized over the lifetimes,
which multiply quickly.

For cases like that I'd rather start with a GC reference, and gradually remove
GC references where time permits and profiling dictates.

I think Rust can really have the best of both worlds here.

BTW: I did manage to finish a fairly involved analysis program in Rust without
using any GC, and I'm really very happy with the results. Being able to GC a
few references would have made things easier though.

~~~
kibwen

      > For cases like that I'd rather start with a GC 
      > reference, and gradually remove GC references where time 
      > permits and profiling dictates.
    

Long ago this was one of the original theses of Rust, that you'd favor GC'd
objects at first and then we'd provide easy ways to transition your code to
use linear lifetimes where profiling deemed necessary.

It took us a long time and boatloads of iteration to finally realize that this
just wasn't feasible. The semantics of GC'd pointers and linear types are just
too drastically different, especially with how they interact with mutability
and inter-task communicability. We "officially" abandoned GC in the language
itself last October, and we're _still_ trying to wrest the last vestiges of
its use out of the compiler itself. Ask pcwalton how much of his time has been
spent doing exactly that in the past four months. Just yesterday one of our
most tenacious community contributors proudly announced that an all-nighter
had resulted in removing two more instances of GC'd pointers from the
compiler, which required touching "only" a few thousand lines. It's a bad
scene.

So yes, while Rust will still offer GC'd pointers in the standard library,
we've long since learned not to encourage users to reach for them without
great justification. You must understand that once you introduce garbage
collection into your code, it will be very difficult to return from that path.

We've also, in practice, tended to point people toward RC'd pointers (with
weak pointers to handle cycles) whenever anyone needs multiple references to
the same piece of memory. Thanks to linear types, reference counting in Rust
is actually surprisingly cheap (many instances where other languages would
need to bump the refcount are simply achieved by moving the pointer in Rust,
since we can statically guarantee that that's safe).

~~~
sixbrx
Thanks for the backstory, I may have been a bit naive then about how easy it
would be to convert.

Good to hear about RC efficiencies, I assumed they were basically
shared_pointer, I haven't tried using them and will give them a look.

------
nsmnsf
Can someone explain RAII to me? In the way that it's commonly used, it seems
like it really means "stack variables that go out of scope are deallocated",
which seems kind of, well, duh? I don't really understand why it's treated
like a big deal.

(I mostly write C + Obj-C)

~~~
detrino
To better understand the importance of RAII, you might consider what some
other languages offer to solve similar problems.

Consider a C example:

    
    
        int f()
        {
            int ret = -1;
    
            handle * a = acquire_handle(0);
            if (a == NULL) goto fail1;
            handle * b = acquire_handle(1);
            if (b == NULL) goto fail2;
            handle * c = acquire_handle(2);
            if (c == NULL) goto fail3;
    
            // use a, b, c
            ret = 0;
    
            release_handle(c);
            fail3:
            release_handle(b);
            fail2:
            release_handle(a);
            fail1:
            return ret;
        }
    

Consider a C# example:

    
    
        void f()
        {
            using (handle a = new handle(0))
            using (handle b = new handle(1))
            using (handle c = new handle(2))
            {
                // use a, b, c
            }
        }
    

Now a C++ example using RAII:

    
    
        void f()
        {
            handle a{0};
            handle b{1};
            handle c{2};
            // use a, b, c
        }
    

These examples are mostly equivalent (Although the C#/C++ assume exceptions
instead of error codes).

The C#/C++ examples are far more structured and less error prone than the C
example.

The advantage of C++'s RAII over C#'s using statement is that cleanup is tied
to the object rather than a statement. This means that RAII is both composable
and non-leaky as an abstraction. You cannot forget to destruct an object in
C++, and you don't have to care that its destructor frees resources. When you
have an IDisposable member in C# you must manually mark your class as
IDisposable and then implement the Dispose method yourself. Clients must also
be aware that your class is IDisposable in order to use it correctly.

~~~
ygra
Stylistic side note for C#: If you're nesting using blocks like that you can
leave out the braces in all but the deepest instance which reads a little
nicer, imho:

    
    
            using (handle a = new handle(0))
            using (handle b = new handle(1))
            using (handle c = new handle(2)) {
                // use a, b, c
            }

~~~
dkuntz2
That actually looks terrible to me, but I don't program in C#. Mostly it's
because there are three blocks, but it only looks like there's one.

~~~
ygra
It gets rid of excessive nesting when you need multiple resources allocated
after another (e.g. SqlConnection, SqlCommand, etc.). You can do

    
    
            using (handle a = new handle(0), b = new handle(1), c = handle(3)) {
                // use a, b, c
            }
    

instead, too, but that obviously only works with equal types.

I'm usually not a friend of too deep nesting (worst thing I've seen in our
codebase was 65 spaces deep) and in C# you already have one level for the
class, one for the namespace (possibly) and another for the method. No need to
add two more if you can help it.

~~~
dkuntz2
Right, I understand that it removes excessive nesting, but the first example
just looked ... wrong to me. Your example with above looks somewhat better.

------
Suncho
I find it interesting that nobody mentions iterators anywhere in this
discussion. One of the main uses of pointers is to iterate through data.
Pointers are the most basic form of iterators in C++. STL iterators are based
on, and often implemented in terms of, pointers.

------
joe_the_user
One interesting thing is that the QT framework prefers the use of pointers
over reference variables. There's actually some reasonable logic here. Pointer
syntax clearly shows you are acting on something in a different way than you
act on an "ordinary" object. Reference object syntax is the same as ordinary
object syntax but you are making changes that will go beyond the local scope
and that is thus less obvious.

With this approach, you can still allocate objects on the stack - you then
take their address and pass that to a subroutine.

~~~
acchow
Presumably, this pointer vs. reference debate is only relevant in C and no
longer has a place in C++ with the use of unique_ptr, shared_ptr, std::move,
etc?

~~~
ori_b
C has no references -- 'type& param' \-- so there is no debate. This is a
topic exclusive to C++, and isn't affected by smart pointers, which overload
all the pointer operators in order to act like regular pointers, only with
some sort of lifetime management.

------
orionblastar
I audited a few MOOC classes.

They don't even bother to teach pointers, the stack, or heap. It just confuses
the students they claim. Also teach students to store the value of PI into an
Integer. Use DRJava and Java 6 and some bloated JAR library that makes Windows
crash.

When I studied computer science in 1986, the very first things we learned
where how memory and binary worked, plus what a pointer was and why it should
be used and how to manage memory so it would not crash and lock up. We learned
how to debug as well.

Most comp sci graduates that I talk to know almost nothing of how a pointer
works, or the stack or heap, and binary might as well be Tagalog to them.

I think that over the years as the demand for IT workers increased, they
relaxed the standards they used in teaching computer science and programming.

Any good MOOC should teach:

Pointers

The Stack

The Heap

Binary

Hexadecimal

How to debug code

Assembly Language instructions the code gets converted into and how to debug
that

------
EGreg
One is allocating on the stack and one on the heap.

Allocating on the heap means you have to delete it yourself in C++.

It's pretty staightforward, no?

------
Jonathan_Swift
It's not always obvious. Quite commonly one is used when the other would be
better, even by otherwise good coders.

To beat the subject completely to death:

Pointers, References and Values

Passing Parameters, Returning Results, and Storing Member Variables with
Musings on Good C++ Style

[http://www.warplife.com/tips/code/c++/memory-
management/para...](http://www.warplife.com/tips/code/c++/memory-
management/parameters/)

