5

In one of the comments in this question, it was brought out that initializing C++ pointers by default would break compatibility with C.

That's fine, but why would something like this matter? I would think the only time it would actually matter is if I wanted an uninitialized pointer for some reason. But I can't think of a reason why I would want to have that.

Is there a use for uninitialized pointers? Or is the compatibility issue merely one of compatible behavior (i.e., not increasing overhead) and not one of breaking code?

Community
  • 1
  • 1
John
  • 15,990
  • 10
  • 70
  • 110
  • Certain load-in-place techniques REQUIRE that pointers are not initialized by the C++ constructor. – Adisak Dec 16 '09 at 00:56
  • Actually, those load-in-place techniques are hacks. If C++ was different, there would be different hacks. E.g. cast raw memory, then memcpy() the vtable pointers in. – MSalters Dec 16 '09 at 10:24
  • Total hacks... I agree -- but a very commonly used hack in my industry (video game programming). They work on VC++ and GCC and every other C/C++ compiler I've used. And working hacks get used. You have to realize by the standard, that something as simple as just assuming a right shift on a signed integer will be arithemetic rather than logical is technically a "hack" as well. – Adisak Dec 16 '09 at 16:55
  • @MSalters: BTW, the technique you describe with cast & memcpy() can be used in pure-C for Load-In-Place if you are emulating Virtual-Functions through an explicit VFTable-pointer entry in a POD struct. It's more convenient to do it in C++ because after the initial fixup hack, the code to use the objects (normal C++) is much cleaner than jumping thru VF-emulation hoops. – Adisak Dec 16 '09 at 17:21

10 Answers10

17

This is a very specialized optimized case for Video Games (basically an embedded system). We used to use them for Load-In-Place data behavior in our Video Games to speed up loading (and avoid fragmentation).

Basically we would create console-side (Playstation) objects in a PC cooker. Then to reduce fragmentation overload, we would pack the data objects in a contiguous buffer with a single alloc. References to the data objects in this buffer would then be changed to subtract the base from pointers to offsets (unfix call -- we also had a virtual fix / unfix calls that took the buffer base and could convert between offsets and pointers).

When we loaded the data, it loaded in one large block. All data referenced by the root was off the root object. We could do an inplace "new" on the the root that would initialize the proper VF tables for the object and fixup all the attached blocks (by doing inplace new and then fixing up attached blocks respectively).

We needed the constructors called (in place new) to generate the proper VF-Tables in the objects. However, if the pointers were automatically cleared to NULL during the constructor, we would have lost the offset data and not been able to recreate the pointers between the objects within the contiguous block.


FWIW, this is a common technique in the Video Game world. This Gamasutra article (not written by me or my coworkers) explains in detail the similar thing they did at another company:

Also, this topic of discussion on SourceForge.

There have even been several GDC (Game Developer Conference) talks on the subject.

Searching on Google for "load-in-place" will give many other examples of people using this technique that basically requires uninitialized pointers.


NOTE: Currently, this is the only response that actually answers the question asked ("Is there a use for uninitialized pointers in C or C++?") by giving a specific use for pointers that must remain unitialized.

All the other responses are better answers for the original question referenced ("[C++] Why aren’t pointers initialized with NULL by default?") that caused the poster to ask this question.

Community
  • 1
  • 1
Adisak
  • 6,708
  • 38
  • 46
  • You do realize that what you've described is one huge non-portable, implementation-specific hack, right? In particular, there's no guarantee that any byte fiddling you may do in the memory in which you will then placement-new an object will reflect in any particular way in the values of the fields of that object. Not only that, but non-PODs (and you mention vtables, so those are non-PODs) have implementation-defined amount of extra data at start, and of course padding between field is also implementation-defined. – Pavel Minaev Dec 15 '09 at 23:22
  • 10
    Yes I do. We used it on very specific cases on PS and XBOX. The question asked if there were a reason to do something. We did it because it made loading our game take seconds instead of minutes (large single block load instead of many little objects created and loaded). It also saved a ton of memory and fragmentation. In the Video Game world (and embedded systems in general), these types of hacks are often necessary to hit performance and memory goals. – Adisak Dec 15 '09 at 23:33
  • note he said "embedded systems". it sounds to me like as far as optimization was concerned, it was justified free for all. – Matt Joiner Dec 15 '09 at 23:34
  • Yeah... this is the fun we had in the old days working on systems that had less total memory than current PC's have for L1 cache. – Adisak Dec 15 '09 at 23:38
11

First of all, initializing pointers (or any other variables) by default does not break compatibility with C. Both C and C++ state that a value of uninitialized variable is indeterminate; in practice, this means that it can hold any value (including a trap representation), but note that 0 belongs to the set of "any values"! So a conformant implementation can perfectly well initialize all pointers to 0. Your program, should it rely on that, would not be conformant, however.

Now as to why you may want your pointer to not be initialized: mainly when it is written to afterwards. For example:

void foo(int*& p) {
   p = new int;
}

int* p; // why initialize? we overwrite it anyway
foo(p);

You can say that compiler should be able to optimize this away. Unfortunately, it cannot do so if the definition of foo is not available (e.g. global link-time optimizations are disabled; or they are enabled, but the function is in a DLL), since it doesn't know if foo will try to read from p (and then initialization would be needed), or if it would just write to it (and then initialization isn't needed). What more, there may be cases that are harder to analyze; for example:

bool try_parse_int(const char* s, int& n)
{
    // if parsed successfully, assign result to n and return true
    // if there was error parsing, don't touch n and return false
    ...
}

int n;
if (try_parse_int(s, n)) {
    // use n here
    ...
} else {
   // don't use n here
   ...
}

This one is much harder for the compiler to analyze even if it has full definitions of all functions.

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
8

Initializing a pointer takes some time. Most of the time you shouldn't care about that, but there are rare occasions when it would make a difference. One of the guiding principles of C (and by extension C++) is never make you pay for something you might not need Don't pay for what you don't use.

Another rare case might come up in embedded programming, where a variable corresponds to a hardware register. Putting a value in the register will start the hardware performing some action which might be detremental.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Isn't it rather: "Don't pay for what you don't use."? – pmr Dec 15 '09 at 23:12
  • Makes me think of the old Fram Oil Filter commercial -- Pay me now, or pay me later. Back when I was doing commercial products in C we used our own memory allocator. In debug mode we would initialize all memory blocks to 0xa5a5a5a5. When something blew up you could immediately tell that something didn't get initialized. – Peter Rowell Dec 15 '09 at 23:15
  • @Peter: I've seen remember 0XDEADBEEF from back in the day for Amiga memory freed to kernel. MS VC++ debug uses 0xFD, 0XDD, 0XCC, and 0xCD for debug patterns as well. – Adisak Dec 16 '09 at 00:38
  • @Adisak, the compiler is free to initialize memory even if you don't do so explicitly. Usually this is reserved for "debug" builds. Some people have an issue with explicitly initializing pointers to nonsense values, but I think that's overreacting. – Mark Ransom Dec 16 '09 at 02:17
  • @Mark: Yep and this is exactly what VC++ does in debug builds for global, static, and local (stack) variables as well as patterning initially allocated memory. It does not however do any initialization of memory during constructors so you can do the in-place new over preformatted data hack. I just wrote a console memory system and I am adding a non-sense pattern initialization to it for debug purposes (it can be turned on/off easily) – Adisak Dec 16 '09 at 06:09
7

Use for an unitialised pointer? See std::strtol().

char * bad;
long n = std::strtol( "123xyz", &bad, 10 );

after this call, bad will contain a pointer to 'x'. There is no point in initialising it.

2

If you were to write a C style program in C++ but assumed pointers were initialized, then took that program back to a C compiler, it would fail to work. That's the only reason I could imagine it mattering.

Bill K
  • 62,186
  • 18
  • 105
  • 157
2

It wouldn't break compatibility with C - a C implementation in which all unintialised pointers are actually initialised to 0 (or indeed, to anything at all!) would be perfectly conforming.

caf
  • 233,326
  • 40
  • 323
  • 462
1

Not having to pay for what you don't need is not here for compatibility with C. It's one of the most important principles of C++ too.

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

An uninitialized pointer is useful for one thing, and one thing only: Assigning something to it. The only reason you'd ever want one is that you don't have a fixed initial value, but plan on assigning one at some point in the future, and thus initializing it is a waste. You could assign it to NULL, if you wanted, or something else.

Since in C++ you can declare variables anywhere in a scope, and not just the start, this is no longer really relevant, since you could just declare it where you use it.

The short answer, though, is no. Just assign it to NULL.

McPherrinM
  • 4,526
  • 1
  • 22
  • 25
0

I'm not sure what comment you're talking about, but I think it only breaks syntactical compatibility. There's no use of uninitialized pointer, but there's also no use to initialize it before you know the value you want to put in there and we don't want to waste time on it.

Michael Krelin - hacker
  • 138,757
  • 24
  • 193
  • 173
0

Suppose you have a function that is an interrupt handler that requires a lot of pointer stack variable(s):

void interruptHandler()
{
    char* ptr0;
    ...
    char* ptrX-1;
    char* ptrX;
}

Suppose its crucial you get in-and-out as fast as possible. You don't want to waste any needless time initializing to defaults, you know you'll try to be safe setting your pointersto something valid later.

Doug T.
  • 64,223
  • 27
  • 138
  • 202
  • This is actually much less of a big deal these days, because a modern optimising compiler would in most cases be able to prove to itself that the "initialised" value was always overwritten, and so safely omit it in the compiled form. (By the way, `ptrX-1` isn't a valid variable name ;) – caf Dec 15 '09 at 23:17
  • @caf, that's probably true unless your platform only has a c compiler written by "Joe's Compiler Shop" :) – Doug T. Dec 15 '09 at 23:32
  • Hey.. are you makin' fun of our compilers, or are you just unassuming?? Either way, 'dems fightin' words. – San Jacinto Dec 16 '09 at 00:18