views:

844

answers:

15

I guess this have been answered before, but I just couldn't find the answer here or on Google, but I think that it is because I couldn't type the right question...

Can someone please explain why aren't pointers initialized to NULL?
Example:

  void test(){
     char *buf;
     if (!buf)
        // whatever
  }

The program wouldn't step inside the if because buf is not null.

I would like to know why, in what case do we need a variable with trash on, specially pointers addressing to trash on the memory?

+6  A: 

For historical reasons, mainly because this is how it is done in C. Why it is done like that in C, is another question, but I think that the zero overhead principle was involved somehow in this design decision.

AraK
I guess because C is considered lower level language with easy access to memory (aka pointers) so it gives you freedom do what you want and does not impose overhead by initializing everything. BTW I think it depends on the platform because I worked on linux based mobile platform that initialized all it's memory to 0 before use so all variables would be set to 0.
stefanB
+13  A: 

Because initialisation takes time. And in C++, the very first thing you should do with any variable is to explicitly initialise it:

int * p = & some_int;

or:

int * p = 0;

or:

class A {
   public:
     A() : p( 0 ) {}  // initialise via constructor
   private:
     int * p;
};
anon
k, if initialization takes time and I still want it, is tehre anyhow to make my pointers come null without setting it manually? see, not because I don't want to right it, because I seem that I will never ever use unitiliazed pointers with trash on their address
Jonathan
another thing after your edit... its easy when it is inside a function, but different when you are using class members, you can;t intialize them within the class scope declaration, right? then you msut do it on the constructor or a init function
Jonathan
No, there is no way of doing that with raw pointers. You may for some purposes be able to use smart pointers, which will normally be initialised to zero.
anon
You initialise class members in the class's constructor - that's how C++ works.
anon
@Jonathan: but null is trash too. You can't do anything useful with a null pointer. Dereferencing one is just as much an error. Create pointers with proper values, not nulls.
DrPizza
Initialising apointer to Nnull can be a sensible thing to do.And there are several operations you can perform on null pointers - you can test them and you can call delete on them.
anon
If you're never going to use a pointer without explicitly initializing it, it doesn't matter what it contained before you gave it a value, and under the C and C++ principle of paying for only what you use, it isn't done automatically. If there is an acceptable default value (usually the null pointer), you should initialize it. You can initialize it or leave it uninitialized, your choice.
David Thornley
@DrPizza - I agree to a certain extent that both situations create an error but I disagree that `NULL` is trash as well. Using a null pointer has defined results whereas using an uninitialized pointer has undefined results which are harder to debug.
Andrew Hare
+1 By the way, good answer.
Andrew Hare
@Andrew Hare: Maybe a null pointer does not yield as defined a result as some linux kernel folks thought it would...
dionadar
@Neil Butterworth: shit, sometimes you can even dereference them, too. I guess you have a different threshold for usefulness than I do.
DrPizza
@DrPizza No, you can't, not if the dereference actually happens. The closest you can do is sizeof(*p) where p contains 0, because sizeof does not cause evaluation of its parameter, so the dereference never actually happens. Any other attempt to dereference a null pointer is undefined by te C++ standard.
anon
You can call delete on a null pointer, so that's a good reason to initiailise it to null then you can call delete on it even if it never gets set to anything. If you don't set it to 0 and your initialisation fails it can be hard to know if you need to, or can, safely delete the data
John Burton
@Neil Butterworth: There are implementations in which you can safely dereference null pointers; they have pages mapped at offset zero.
DrPizza
@JB: Why create the pointer before you can assign a useful value to it? And why not use RAII to ensure that cleanup occurs properly no matter what?
DrPizza
@DrPizza The actual representation of the null pointer need not be zero. And even if it is, your putative architecture would still give undefined behaviour in C++ terms.
anon
Lots of things give undefined behaviour. It is hardly significant.
DrPizza
+13  A: 

Quoting Bjarne Stroustrup in TC++PL (Special Edition p.22):

A feature's implementation should not impose significant overheads on programs that do not require it.

John at CashCommons
and don't give the option, either. It seems
Jonathan
@ Jonathan nothing prevents you from initializing pointer to null - or to 0 as is standard in C++.
stefanB
The "feature," in this case, is allocating the pointer. Loading it with NULL automatically would be "imposing significant overheads."
John at CashCommons
@Jonathan: You've got the option. You can initialize it to the null pointer, or you can leave it as garbage. C was developed as a systems implementation language, and C++ continues that tradition. The language will try its best not to do anything you don't ask for.
David Thornley
Yes, but Stroustrup could have made the default syntax favour program correctness rather than performance by zero-initializing the pointer, and make the programmer have to explicitly request the pointer to be uninitialized. After all, most people prefer correct-but-slow over fast-but-wrong, on the grounds that it is generally easier to optimize a small amount of code than fix bugs in the entire program. Especially when much of it can be done by a decent compiler.
Robert Tuck
This would break C compatibility, which is a big issue.
anon
@Neil: in which way would it break C compatibility? Any conformant C code that is also conformant C++ now would remain conformant if C++ suddenly started guaranteeing 0-initialization for pointers. Or do you mean that C++ code written with such assumption wouldn't be conformant C where it otherwise could?
Pavel Minaev
It doesn't break compatibility. The idea has been considered in conjunction with "int* x = __uninitialized" - safety by default, speed by intent.
MSalters
@Jonathan, well your compiler might initialize everything to 0xDEADBEEF or something in debug mode.
iconiK
I like what `D` does. If you do not want initialization use this syntax `float f = void;` or `int* ptr = void;`. Now it is initialized by default but if you really need to you can stop the compiler from doing it.
caspin
+4  A: 

There are vanishingly few situations in which it ever makes sense for a variable to be uninitialized, and default-initialization has a small cost, so why do it?

C++ is not C89. Hell, even C isn't C89. You can mix declarations and code, so you should defer declaration until such a time as you have a suitable value to initialize with.

DrPizza
Then just every value will need to be written to twice -- once by the compiler's setup routine, and again by the user's program. Not usually a big problem, but it adds up (e.g. if you are creating an array of 1 million items). If you want auto-initialization you can always create your own types that do that; but this way you aren't forced to accept unnecessary overhead if you don't want to.
Jeremy Friesner
+5  A: 

Besides, we do have a warning for when you blow it: "is possibly used before assigned a value" or similar verbage depending on your compiler.

You do compile with warnings, right?

Joshua
+2  A: 

A pointer is just another type. If you create an int, char or any other POD type it isn't initialised to zero, so why should a pointer? This could be considered unnecessary overhead to someone who writes a program like this.

char* pBuf;
if (condition)
{
    pBuf = new char[50];
}
else
{
    pBuf = m_myMember->buf();
}

If you know you're going to initialise it, why should the program incur a cost when you first create pBuf at the top of the method? This is the zero overhead principle.

LeopardSkinPillBoxHat
on the other hand you could do char *pBuf = condition ? new char[50] : m_myMember->buf();It's more like a matter of syntax then efficiency but I stll agree with you nevertheless.
the_drow
A: 

Well, if C++ did initialize pointers, then the C folks complaining "C++ is slower than C" would have something real to hang on to ;)

Fred
A: 

Another possible reason why, is that at link-time pointers are given an address, but the indirect addressing/de-referencing a pointer is the responsibility of the programmer. Quite ordinarily, the compiler does not care less, but the burden is passed on to the programmer to manage the pointers and to make sure that no memory leaks occur.

Really, in a nutshell, they are initialized in the sense that at link-time the pointer variable is given an address. In your example code above, that is guaranteed to crash or generate a SIGSEGV.

For the sake of sanity, always initialize pointers to NULL, in that way if any attempt to dereference it without malloc or new will clue the programmer into the reason why the program mis-behaved.

Hope this helps and make sense, Best regards, Tom.

tommieb75
+1  A: 

Note that static data is initialized to 0 (unless you say otherwise).

And yes, you should always declare your variables as late as possible and with an initial value. Code like

int j;
char *foo;

should set off alarm bells when you read it. I don't know if any lints can be persuaded to carp about it though since it's 100% legal.

pm100
is that GUARANTEED, or just a common practice used by todays compilers?
dionadar
static variables are initialized to 0, which does the right thing for pointers too (i.e., sets them to NULL, not all bits 0). This behavior is guaranteed by the standard.
Alok
initialization of static data to zero is guaranteed by the C and C++ standard, it's not just common practice
groovingandi
perhaps because some people want to make sure that their stack is nicely aligned they pre-declare all variables at the top of the function? Maybe they are writting in a c dialect that REQUIRES this?
KitsuneYMG
A: 

C++ comes from a C background - and there are a few reasons coming back from this:

C, even more than C++ is an assembly language replacement. It does not do anything you do not tell it to do. Therefor: If you want to NULL it - do it!

Also, if you null things in a bare-metal language like C automatically consistency questions crop up: If you malloc something - should it automatically be zeroed? What about a struct created on the stack? should all bytes be zeroed? What about global variables? what about a statement like "(*0x18);" does that not then mean that memory position 0x18 should be zeroed?

dionadar
Actually, in C, if you want to allocate all-zero memory you can use `calloc()`.
David Thornley
just my point - if you want to do it, you can, but it is not done for you automagically
dionadar
A: 

Because one of the pillars of C++ is :


You don't pay for what you don't need


For this very reason, the operator[] of the vector class does not check if the index is out of bounds, for instance.

Samuel_xL
+17  A: 

We all realize that pointer (and other POD types) should be initialized.
The question then becomes 'who should initialize them'.

Well there are basically two methods:

  • The compiler initializes them.
  • The developer initializes them.

Let us assume that the compiler initialized any variable not explicitly initialized by the developer. Then we run into situations where initializing the variable was non trivial and the reason the developer did not do it at the declaration point was he/she needed to perform some operation and then assign.

So now we have the situation that the compiler has added an extra instruction to the code that initializes the variable to NULL then later the developer code is added to do the correct initialization. Or under other conditions the variable is potentially never used. A lot of C++ developers would scream foul under both conditions at the cost of that extra instruction.

It's not just about time. But also space. There are a lot of environments where both resources are at a premium and the developers do not want to give up either.

BUT: You can simulate the effect of forcing initialization. Most compilers will warn you about uninitialized variables. So I always turn my warning level to the highest level possible. Then tell the compiler to treat all warnings as errors. Under these conditions most compilers will then generate an error for variables that are unused and used and thus will prevent code from being generated.

Martin York
This is one of my favorite answers on SO.
AraK
Very nice answer.
John at CashCommons
A: 

What are these pointers you talk about?

For exception safety, always use auto_ptr, shared_ptr, weak_ptr and their other variants.
A hallmark of good code is one that doesn't include a single call to delete.

shoosh
+1  A: 

If you want a pointer that is always initialized to NULL, you can use a C++ template to emulate that functionality:

template<typename T> class InitializedPointer
{
public:
    typedef T  TObj;
    typedef TObj *PObj;
protected:
    PObj  m_pPointer;

public:
    // Constructors / Destructor
    inline InitializedPointer() { m_pPointer=0; }
    inline InitializedPointer(PObj InPointer) { m_pPointer = InPointer; }
    inline InitializedPointer(const InitializedPointer& oCopy)
    { m_pPointer = oCopy.m_pPointer; }
    inline ~InitializedPointer() { m_pPointer=0; }

    inline PObj GetPointer() const { return (m_pPointer); }
    inline void SetPointer(PObj InPtr) { m_pPointer = InPtr; }

    // Operator Overloads
    inline InitializedPointer& operator = (PObj InPtr)
    { SetPointer(InPtr); return(*this); }
    inline InitializedPointer& operator = (const InitializedPointer& InPtr)
    { SetPointer(InPtr.m_pPointer); return(*this); }
    inline PObj operator ->() const { return (m_pPointer); }
    inline TObj &operator *() const { return (*m_pPointer); }

    inline bool operator!=(PObj pOther) const
    { return(m_pPointer!=pOther); }
    inline bool operator==(PObj pOther) const
    { return(m_pPointer==pOther); }
    inline bool operator!=(const InitializedPointer& InPtr) const
    { return(m_pPointer!=InPtr.m_pPointer); }
    inline bool operator==(const InitializedPointer& InPtr) const
    { return(m_pPointer==InPtr.m_pPointer); }

    inline bool operator<=(PObj pOther) const
    { return(m_pPointer<=pOther); }
    inline bool operator>=(PObj pOther) const
    { return(m_pPointer>=pOther); }
    inline bool operator<=(const InitializedPointer& InPtr) const
    { return(m_pPointer<=InPtr.m_pPointer); }
    inline bool operator>=(const InitializedPointer& InPtr) const
    { return(m_pPointer>=InPtr.m_pPointer); }

    inline bool operator<(PObj pOther) const
    { return(m_pPointer<pOther); }
    inline bool operator>(PObj pOther) const
    { return(m_pPointer>pOther); }
    inline bool operator<(const InitializedPointer& InPtr) const
    { return(m_pPointer<InPtr.m_pPointer); }
    inline bool operator>(const InitializedPointer& InPtr) const
    { return(m_pPointer>InPtr.m_pPointer); }
};
Adisak
If I were implementing this, I wouldn't bother with te copy ctor or the assignment op - the defaults are quite OK. And your destructor is pointless. You can of course also test pointers using the less than operater et all )in some circumstances) so you should provide them.
anon
OK, less than is trivial to implement. I had the destructor so that if the object goes out of scope (i.e. local defined within a subscope of a function) but is still taking space on the stack, the memory is not left as a dangling pointer to garbage. But dude seriously, I wrote this in under 5 min. It's not meant to be perfect.
Adisak
OK added all the comparison operators. The default overrides may be redundant but they are here explicitly since this is an example.
Adisak
I couldn't understand how this would make all the pointers null without seting them manually, could you explain what u did here please?
Jonathan
@Jonathan: This is basically a "smart pointer" that does nothing other than set the pointer to null. I.E. instead of `Foo *a`, you use `InitializedPointer<Foo> a` - A purely academic excercise as `Foo *a=0` is less typing. However, the code above is very useful from an educational standpoint. With a little modification (to the "placeholding" ctor/dtor and assignment ops), it could be easily extended to various types of smart pointers including scoped-pointers (which free on the destructor) and reference-counted-pointers by adding inc/dec operations when the m_pPointer is set or cleared.
Adisak
A: 

Oh boy. The real answer is that it is easy to zero out memory, which is basic initialization for say a pointer. Which also has nothing to do with initializing the object itself.

Considering the warnings most compilers give at highest levels I can't imagine programming at the highest level and treating them as errors. Since turning them up has never saved me even one bug in huge amounts of code produced I can't recommend this.

Charles Eli Cheese