tags:

views:

285

answers:

8

This is a C++ class that I have made with n number of pointers.

class SomeClass
{
private:
     int* ptr1;
     int* ptr2;
     ...
     int* ptrn;

private:
     // constructors, destructors, and methods
};

During the initialization stage, I want to make all those pointers point to NULL (or make pointers point to NULL by default when they are declared) rather than doing so:

void SomeClass::MakePtrNull()
{
     ptr1 = NULL;
     ptr2 = NULL;
     ...
     ptrn = NULL;
}

Is there any easy method of accomplishing this goal? I'm just wondering if there are any ways of avoiding typing n lines of ptr = NULL; in my function. Thanks in advance.

ADDED based on the answers that I have received so far: Unfortunately, those pointers have to be separate, as they are used for different purposes. I made the names of the pointers as such just to make a point of what I'm trying to do, but each pointer has a completely different purpose. I guess I would have to make them point to NULL as I have done already. Thanks for your answers.

+6  A: 

Why don't you use an array or a vector rather than creating n individually named pointers? Then you can do the nulling in a short for loop.

+5  A: 

You can do this:

void SomeClass::MakePtrNull()
{
        ptr1 = ptr2 = ptr3 = ... = ptrn = NULL;
}
Eclipse
+3  A: 

First, the technique that does not work:

Calling memset to set the entire object to zero won't do. First, it'll cause a lot of trouble if your function has one or more virtual functions, and second, a null pointer is not guaranteed to be represented by a bit pattern of all zeros.

What I would probably do in your case is store the pointers in an array or a vector. Then you can use the std::fill function to set them all to NULL. (Or you could use a loop if you prefer)

Of course, if you need to do this often enough, it may be worth writing a wrapper class which behaves as the pointer, but which sets it to NULL in its default constructor.

Or you could use boost::optional which works essentially like this. (although it is not specific for pointers)

jalf
You say that a null pointer is not guaranteed to be presented by a bit pattern of all zeros, does that imply that an if check like this: if(ptr1)is not a safe way of determining that a pointer is not null?
Andrew Garrison
Yes, please do elaborate on what scenario 0x0 is not a valid 'no memory allocated here' address.Also, if the struct/class (as well as its parent classes) has no virtual methods then its sizeof will be exactly the sum of the sizeofs of its members.
Shane Arney
@average. That is safe. A NULL ptr must evaluate false, but the implementation can represent it in memory however it likes. In practice pretty much everyone does use 0, because a NULL ptr also must cast to integer as 0 and it's usually easiest and most efficient not to change the bit pattern. @Shane: the struct needs to be POD for what you say to be guaranteed by the standard. There are other things than virtual methods which can cause a struct to be non-POD, and having any base classes is one of them.
Steve Jessop
@Shane: There's not much to elaborate on. It usually follows the CPU architecture. On some machines, address 0 may be a valid address, and another value is conventionally used for "null". Or on machines with segmented memory models, the "null" value might be something other than a plain 0x0 too. On most computers, there's no difference between the value zero and the value of a null pointer, but in C++-standard-land, it is not guaranteed to be the case, for the sake of portability.
jalf
In C++, NULL is always 0.See http://www.research.att.com/~bs/bs_faq2.html
Mike Kale
NULL is not a null pointer. It's a null pointer constant, which is 0. jalf talks about a null pointer, which is *not* 0, but a pointer that points to no object or function. It also does not convert back to 0. The conversion is only from 0 *to* a null pointer - however it converts to bool with false. For information on the difference, see http://stackoverflow.com/questions/651361/boolean-datatype-question/651378#651378
Johannes Schaub - litb
I've always thought of a null pointer as being a pointer with the value NULL, which in C++ is always 0. A more general pointer that does not point at a valid object may or may not be null. In any case, OP was asking for a way to make all those pointers point to NULL.
Mike Kale
The OP does not know the correct terms, i'm afraid. You can assign NULL to a pointer, but you cannot make a pointer "point to NULL", of course.
Johannes Schaub - litb
I know I should have been more precise or litb would come and correct me. ;)@Mike: NULL is always 0, yes, but a null pointer is not a pointer to the address zero. When the constant 0 is assigned to a pointer, magic happens. The bit pattern zero is *not* simply copied into the pointer. Instead, the pointer is set to some implementation-defined state which *may or may not* use the all-zero bit pattern.
jalf
+2  A: 

Why not use a default constructor:

SomeClass::SomeClass() : ptr1(NULL), ptr2(NULL), ...
{

}

You could also do:

ptr1 = ptr2 = ptr3 = NULL;
Alan
A: 

Use a vector for this (because by the sounds of it you won't need to ever edit the list in the future - and you need random access). You can do it like this:

class PointerList
{
private:
    typedef std::vector<int*> IntPtrVector;
    IntPtrVector m_ptrVec;

public:
    PointerList()
    {
        m_ptrVec.reserve(5);
        for (int i = 0; i < 5; i++)
            m_ptrVec.push_back(NULL);
    }

    int* getPointer(int index)
    {
        return m_ptrVec[index];
    }

    void setPointer(int index, int* ptr)
    {
        assert(index <= 4);
        m_ptrVec[index] = ptr;
    }
};

EDIT

Though to be honest this reeks of ghettoness. Are you sure your problem requires this solution? If you elaborate more on your specific problem, in another question perhaps, I'm sure you can get some better answer on how to accomplish what you want more elegantly - rather then by creating a second problem.

nlaq
The whole point of the question is asking whether if I can take a lazy way out yet that works. Thanks for your time on the suggestions though.
stanigator
+11  A: 

Instead of int *, create a smart-pointer-like class which works exactly like a int *, but default-constructs with NULL:

template <typename T>
class MyPointer {
    T *p;

public:
    MyPointer() : p(NULL) { }
    MyPointer(T *o) : p(o) { }
    operator T*() const { return p; }
    // ...and the rest of the traditional smart-pointer operators
};

Then, use it in your class:

class SomeClass
{
private:
        MyPointer<int> ptr1;
        MyPointer<int> ptr2;
        ...
        MyPointer<int> ptrn;

private:
        // constructors, destructors, and methods
};

Every variable of the MyPointer<int> type will be automatically initialized correctly in SomeClass's constructors, without the need for any extra typing. If you did not forget or incorrectly implement any of MyPointer's methods, it will act exactly like a normal pointer, and have the exact same size and performance.

CesarB
+1 for using the type system to exactly express programming intent.
Thomas L Holaday
Another benefit is that you and the code maintainers will not need to initialize the pointers in every constructor, or remember to update initializer lists should the number or name of MyPointer members change.
Thomas L Holaday
Also - 0 runtime overhead
Eclipse
+1  A: 

You could put the pointers into a struct and then memset() the struct when needed. The pointers are still separated, but you have the means of targeting them as a single unit without affecting the rest of your class. For example:

struct MyPointers
{
    int* ptr1;
    int* ptr2;
    ...
    int* ptrn;
};

class SomeClass
{
private:
    MyPointers ptrs;
    ...
};

void SomeClass::MakePtrNull()
{
    memset(&ptrs, 0, sizeof(ptrs));
}
Remy Lebeau - TeamB
memset doesn't work like this. see jalf's answer.
Johannes Schaub - litb
+3  A: 

I recommend you to do the following, if you have to keep the pointers separately (probably the most pressing need would be if the pointers can have different types)

class SomeClass {
    struct Pointers {
        int* ptr1;
        int* ptr2;
        float* ptrn;
    } ptrs;

public:
    void MakePtrNull();
};

void SomeClass::MakePtrNull()
{
    // clears all pointers at once
    ptrs = Pointers();
}

This does work, because value-initialization for classes that doesn't have a user declared constructor will value initialize all its members. Value initialization of a pointer will create a null pointer.

Johannes Schaub - litb
That's a great technique. +1
Appu