129

Can someone please explain why pointers aren't 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 the trash on the memory?

Archmede
  • 1,592
  • 2
  • 20
  • 37
Jonathan
  • 4,724
  • 7
  • 45
  • 65
  • 13
    Well, because fundamental types are left uninitialized. So I assume your "real" question: is why aren't fundamental types initialized? – GManNickG Dec 15 '09 at 22:22
  • 11
    "the programm wouldn't step inside the if because buf is not null". That's not correct. Since you don't know what buf *is*, you can't know what it *isn't*. – Drew Dormann Dec 15 '09 at 23:39
  • 1
    In contrast to something like Java, C++ gives a ton more responsibility to the developer. – Rishi Jul 09 '14 at 16:53
  • integers, pointers, default to 0 if you use () constructor. – Erik Aronesty Mar 10 '15 at 18:00
  • 1
    Because of the assumption that someone using C++ is knowing what they are doing, moreover someone who is using a _raw_ pointers over a **smart pointer** knows (even more so) what they are doing! – Lofty Lion Jul 11 '16 at 18:29

15 Answers15

167

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 un-initialized but used and thus will prevent code from being generated.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 5
    Bob Tabor said, "Too many people have not given enough thought to initialization! "Its 'friendly' to initialize all variables automatically, but it takes time, and slow programs are 'unfriendly'. A spread sheet or editors that showed the random garbage malloc found would be unacceptable. C, a sharp tool for trained users (hazardous if misused) shouldn't take time initializing automatic variables. A training wheel macro to init variables could be, but many think its better to stand up, be mindful, and bleed a bit. In a pinch, you work the way you practice. So practice as you'd have it be. – Bill IV Mar 31 '11 at 06:10
  • 2
    You would be surprised at how many bugs would be avoided just by someone fixing all of their initialization. This would be tedious work if it were not for compiler warnings. – Jonathan Henson Feb 09 '12 at 16:34
  • @JonathanHenson: Thanks for stating the obvious (and I am not surprised (its a lot)). Hence the line `We all realize that pointer should be initialized`. But that is not the point of the question. The question asked why are they not and there is a good reason not too (as explained above). Any experienced developer will turn the appropriate warnings on and fix any un-initialized variables. **BUT** why should I be hampered by a requirement that would make your life easier (and that make my code less efficient). You (the generic you) may need training wheels on your bike I (the generic I) don't. – Martin York Feb 09 '12 at 16:48
  • 4
    @Loki, I am having a hard time following your point. I was just trying to commend your answer as helpful, I hope you gathered that. If not I am sorry. – Jonathan Henson Feb 09 '12 at 17:29
  • 3
    If the pointer is first set to NULL and then set to whatever value, the compiler should be able to detect this and optimize the first NULL initialization, right? – Korchkidu Aug 13 '14 at 06:51
  • 1
    @Korchkidu: Sometimes. One of the major problems though is that there's no way for it to warn you that you forgot to do your initialization, as it cannot know the default isn't perfect for your use. – Deduplicator Oct 18 '15 at 15:59
  • It would be really interesting to have hard data on how much (considering modern optimization capabilities) bugfree code would be actually slowed down (or by how much the code size would increase) if the compiler would automatically value-initialize all pods. – MikeMB Jan 09 '16 at 03:56
  • But why don't just initialize pointer types to NULL (and leave other PODs' initialization the way they are)? Won't it save developers' time while does not incur significant overhead? – xtt Dec 12 '17 at 10:47
  • @Jason: What is the difference between POD and pointer? Significant is a relative term. What is not significant to you on your desk top machine is significant to the micro controller with limited space and resource. Also there is a **better** way. Get the compiler to tell you when you forget and generate an error so the code will not compile. That way you force the developer to explicitly make the choice. – Martin York Dec 12 '17 at 16:48
43

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
  • 15,990
  • 10
  • 70
  • 110
  • and don't give the option, either. It seems – Jonathan Dec 15 '09 at 22:28
  • 8
    @ Jonathan nothing prevents you from initializing pointer to null - or to 0 as is standard in C++. – stefanB Dec 15 '09 at 22:30
  • The "feature," in this case, is allocating the pointer. Loading it with NULL automatically would be "imposing significant overheads." – John Dec 15 '09 at 22:31
  • @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 Dec 15 '09 at 22:42
  • 14
    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 Dec 15 '09 at 22:44
  • This would break C compatibility, which is a big issue. –  Dec 15 '09 at 22:48
  • 1
    @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 Dec 15 '09 at 23:32
  • 2
    It doesn't break compatibility. The idea has been considered in conjunction with "int* x = __uninitialized" - safety by default, speed by intent. – MSalters Dec 16 '09 at 10:22
  • @Jonathan, well your compiler might initialize everything to 0xDEADBEEF or something in debug mode. – CMircea Apr 08 '10 at 19:24
  • 4
    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. – deft_code Jul 07 '10 at 18:31
  • @RobertTuck If you "prefer correct-but-slow over fast-but-wrong" then you probably don't choose C++ as your go-to language... C++ happens to have a different philosophy than you, and it has become popular with that philosophy. – Jeff May 22 '13 at 16:53
  • @RobertTuck: Well, are you sure zero-initialization is what you want in every instance? Because the compiler can no longer warn about the missing explicit initialization then... – Deduplicator Oct 18 '15 at 16:01
22

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;
};
  • 1
    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 Dec 15 '09 at 22:24
  • 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 Dec 15 '09 at 22:25
  • 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. –  Dec 15 '09 at 22:26
  • 1
    You initialise class members in the class's constructor - that's how C++ works. –  Dec 15 '09 at 22:27
  • 3
    @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 Dec 15 '09 at 22:29
  • 2
    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. –  Dec 15 '09 at 22:31
  • 4
    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 Dec 15 '09 at 22:33
  • 1
    @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 Dec 15 '09 at 22:33
  • @Andrew Hare: Maybe a null pointer does not yield as defined a result as some linux kernel folks thought it would... – danielschemmel Dec 15 '09 at 22:36
  • @Neil Butterworth: shit, sometimes you can even dereference them, too. I guess you have a different threshold for usefulness than I do. – DrPizza Dec 15 '09 at 22:49
  • @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. –  Dec 15 '09 at 23:11
  • 1
    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 – jcoder Dec 15 '09 at 23:16
  • @Neil Butterworth: There are implementations in which you can safely dereference null pointers; they have pages mapped at offset zero. – DrPizza Dec 16 '09 at 00:18
  • @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 Dec 16 '09 at 00:19
  • @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. –  Dec 16 '09 at 11:18
  • Lots of things give undefined behaviour. It is hardly significant. – DrPizza Dec 16 '09 at 14:18
22

Because one of the mottos of C++ is :


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


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

KeatsPeeks
  • 19,126
  • 5
  • 52
  • 83
11

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.

Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
  • 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 Dec 15 '09 at 22:33
  • Automatically initializing it to zero wouldn't break backwards compatibility with C. If uninitialized variables can be anything, they're also allowed to be zero. – Donald Duck Dec 18 '22 at 18:49
7

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
  • 40,822
  • 8
  • 72
  • 132
5

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
  • 17,882
  • 7
  • 41
  • 53
  • 2
    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 Dec 15 '09 at 23:53
3

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
  • 28,915
  • 15
  • 75
  • 111
  • 1
    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 Dec 15 '09 at 22:33
  • 1
    @the_drow: Well, one can make it more complex just so such a rewriting isn't possible. – Deduplicator Oct 18 '15 at 16:08
3

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
pm100
  • 48,078
  • 23
  • 82
  • 145
  • is that GUARANTEED, or just a common practice used by todays compilers? – danielschemmel Dec 15 '09 at 22:34
  • 1
    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 Singhal Dec 15 '09 at 22:52
  • 1
    initialization of static data to zero is guaranteed by the C and C++ standard, it's not just common practice – groovingandi Dec 15 '09 at 22:53
  • 1
    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 Dec 18 '09 at 10:40
3

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
  • 6,708
  • 38
  • 46
  • 1
    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. –  Dec 15 '09 at 23:14
  • 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 Dec 15 '09 at 23:20
  • OK added all the comparison operators. The default overrides may be redundant but they are here explicitly since this is an example. – Adisak Dec 15 '09 at 23:29
  • 1
    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 Dec 16 '09 at 01:34
  • 1
    @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 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 Dec 16 '09 at 17:09
1

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,

t0mm13b
  • 34,087
  • 8
  • 78
  • 110
0

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
  • 199
  • 2
  • That's not my reason. My reason is that if the hardware has 512 bytes of ROM and 128 bytes of RAM and an extra instruction to zero a pointer is even one byte that is quite a large percentage of the whole program. I need that byte! – Jerry Jeremiah Apr 27 '16 at 05:06
0

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?

danielschemmel
  • 10,885
  • 1
  • 36
  • 58
0

What are these pointers you speak of?

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
  • 76,898
  • 55
  • 205
  • 325
-2

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.