Why aren't pointers initialized with NULL by default?

C++MemoryPointersInitialization

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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.

Solution 3 - C++

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;
};

Solution 4 - C++

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.

Solution 5 - C++

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.

Solution 6 - C++

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?

Solution 7 - C++

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.

Solution 8 - C++

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.

Solution 9 - C++

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.

Solution 10 - C++

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); }
};

Solution 11 - C++

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,

Solution 12 - C++

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

Solution 13 - C++

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?

Solution 14 - C++

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.

Solution 15 - C++

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJonathanView Question on Stackoverflow
Solution 1 - C++Martin YorkView Answer on Stackoverflow
Solution 2 - C++JohnView Answer on Stackoverflow
Solution 3 - C++anonView Answer on Stackoverflow
Solution 4 - C++KeatsPeeksView Answer on Stackoverflow
Solution 5 - C++Khaled AlshayaView Answer on Stackoverflow
Solution 6 - C++JoshuaView Answer on Stackoverflow
Solution 7 - C++DrPizzaView Answer on Stackoverflow
Solution 8 - C++LeopardSkinPillBoxHatView Answer on Stackoverflow
Solution 9 - C++pm100View Answer on Stackoverflow
Solution 10 - C++AdisakView Answer on Stackoverflow
Solution 11 - C++t0mm13bView Answer on Stackoverflow
Solution 12 - C++FredView Answer on Stackoverflow
Solution 13 - C++gha.stView Answer on Stackoverflow
Solution 14 - C++shooshView Answer on Stackoverflow
Solution 15 - C++Charles Eli CheeseView Answer on Stackoverflow