1

I have to create a function that can take in an array of pointers with a known size, and set all the pointers to NULL. The caveat is that I don't know the type beforehand. This is what I have tried so far:

    template <typename T>
  static void Nullify(T** _Array, int _Size, unsigned int _SizeOf)
  {
   for (int i = 0; i < _Size; i++)
   {
    _Array[i * _SizeOf] = NULL;
   }
  }

Which is giving me errors (not the function itself, but I am trampling on memory I should not be trampling on resulting in a memory error later on). I am passing in the array (_Array - already initialized to _Size), its size (_Size), and the sizeof(Pointer*) as _SizeOf.

Any help would be greatly appreciated :)

3
  • 7
    By the way, your parameter names aren't valid. Names beginning with _ followed by an upper case letter are reserved. Commented Jun 26, 2010 at 21:05
  • +1 for pointing out reserved names. Commented Jun 27, 2010 at 13:14
  • Wow, thanks! I had no idea. I will have to change my convention. Commented Jun 28, 2010 at 16:05

5 Answers 5

7

You don't need _SizeOf. This is what you want:

template <typename T>
static void Nullify(T** _Array, int _Size)
{
   for (int i = 0; i < _Size; i++)
   {
      _Array[i] = NULL;
   }
}

The compiler knows the size of a pointer, and does the math for you during the array dereference.

Sign up to request clarification or add additional context in comments.

4 Comments

Each array is presented as a pointer to it's first element. T** means array of pointers - it points to the first pointer in the array
Thanks! I incorrectly assumed that the compiler will not know what type has been passed.
@Samaursa: The compiler knowing the type that has been passed is the point of a template. When you use T, that is the type.
Consider adding an overload template <typename T, size_t Size> void Nullify(T (&Array)[Size]) - why pass the array size yourself when the compiler already knows it?
3
template <class T>
void Nullify(T** the_array, unsigned int size)
{
    std::fill(the_array, the_array + size, static_cast<T*>(0) );
}

template <class T, unsigned int N>
void Nullify(T* (&the_array)[N])
{
    Nullify(the_array, N);
}

The second allows you to pass an array of pointers and nullify it without even passing in a size argument. This requires that you have an actual array to pass in and not a pointer:

Foo* x[10] = {...}
Nullify(x); // sets all pointers in x to 0 (NULL)

... or if you just want to write it out yourself in a loop (this is generally not going to be as fast as std::fill which can even do the actual filling through very efficient assembly code for PODs):

template <class T>
void Nullify(T** the_array, unsigned int size)
{
    for (unsigned int j=0; j < size; ++j)
        the_array[j] = 0;
}

Note that I also avoid using NULL for the same reason Stroustrup does this (avoids the need to include cstddef). When C++0x is more widely implemented, the nullptr keyword will make a nice replacement.

BTW: the static keyword is ignored for function templates. They already have internal linkage so it's superfluous to add it.

9 Comments

+1 for suggesting std::fill or a simple loop; -1 for suggesting memset. See the comments to stackoverflow.com/questions/3124990/…
@Mike (pasted) That's far too pedantic. Let's assume that a compiler special-cases pointer construction such that 0 is converted to the address, 0xFFFFFFFF. Show me one compiler that does anything like this. There won't be any. For years relying on vector to be contiguous invoked undefined behavior (no contiguous guarantees), yet anyone with common sense would know that there's no other sane way to implement std::vector. Ask any C programmer this same question here and they'll answer with memset. It doesn't matter if they use NULL for the second argument because memset accepts an int for val!
[pasted again, apologies but @see original discussion] In fact, Dinkumware's "portable" standard library implementation even uses memset for std::fill with PODs. It's far too widely used of a convention (at least in ANSI C) to implement NULL pointer addresses as anything but 0. It's like arguing that code invoking bitwise comparisons is non-portable because the code assumes a byte to have 8 bits. That, however, is at least a more reasonable argument given that there are existing machines where that isn't the case.
Preferring portable, typesafe C++ idioms to legacy C functions for dealing with raw memory is not pedantry. I've no wish to be drawn into yet another tedious argument about it, but to answer your two points: (a) c-faq.com/null/machexamp.html gives examples of platforms with non-zero null pointers; (b) I don't have $2300 to spare on a Dinkumware source license to check your claim, but I've seen enough shockingly bad commercial code to disregard any claim that any particular practice is acceptable simply because a commercial organisation uses it.
Sometimes it may be necessary to make assumptions about the platform. In this case, there is an easy way to do it portably, so why argue so fervently against using it?
|
1

You shouldn't be doing _Array[i * _SizeOf] = NULL, but rather _Array[i] = NULL.

Comments

1

I agree with Reed's answer, of course you also should remove the '* _SizeOf' in your assignment.

If possible, I would also suggest you move away from "raw" arrays and use a std::vector in your code. It's a safer structure with array-like semantics, and imposes only a little overhead.

1 Comment

In this case I did not have a choice, otherwise I would definitely go with containers
0

You shouldn't rely on the _SizeOf your value to asses it's type, you should use a function to determine it's type.

At what point do you declare your T** _Array? Perhaps here you should make sure your method guarantees a particular type of Array for any part of your program that calls it, right?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.