делая многочисленные указатели NULL одновременно - PullRequest
6 голосов
/ 20 июня 2009

Это класс C ++, который я создал с n указателями.

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

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

На этапе инициализации я хочу, чтобы все эти указатели указывали на NULL (или указатели указывали на NULL по умолчанию при их объявлении), а не так:

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

Есть ли простой способ достижения этой цели? Мне просто интересно, есть ли способы избежать ввода n строк ptr = NULL; в моей функции. Заранее спасибо.

ДОБАВЛЕНО на основании ответов, которые я получил до сих пор: К сожалению, эти указатели должны быть отдельными, так как они используются для разных целей. Я сделал имена указателей как таковые, чтобы показать, что я пытаюсь сделать, но каждый указатель имеет совершенно другое назначение. Я думаю, что я должен был бы заставить их указывать на NULL, как я уже сделал. Спасибо за ваши ответы.

Ответы [ 8 ]

11 голосов
/ 20 июня 2009

Вместо int * создайте класс, подобный интеллектуальному указателю, который работает точно так же, как int *, но по умолчанию конструирует с 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
};

Затем используйте его в своем классе:

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

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

Каждая переменная типа MyPointer<int> будет автоматически правильно инициализирована в конструкторах SomeClass без необходимости какой-либо дополнительной типизации. Если вы не забыли или неправильно реализовали какой-либо из методов MyPointer, он будет действовать точно так же, как обычный указатель, и иметь точно такой же размер и производительность.

6 голосов
/ 20 июня 2009

Почему вы не используете массив или вектор вместо создания n именованных указателей? Тогда вы можете сделать обнуление в цикле for.

5 голосов
/ 20 июня 2009

Вы можете сделать это:

void SomeClass::MakePtrNull()
{
        ptr1 = ptr2 = ptr3 = ... = ptrn = NULL;
}
3 голосов
/ 20 июня 2009

Я рекомендую вам сделать следующее, если вам нужно хранить указатели отдельно (вероятно, наиболее насущная необходимость будет, если указатели могут иметь разные типы)

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

public:
    void MakePtrNull();
};

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

Это работает, потому что инициализация значения для классов, у которых нет объявленного пользователем конструктора, будет инициализировать значение всеми его членами. Значение инициализации указателя создаст нулевой указатель.

3 голосов
/ 20 июня 2009

Во-первых, техника, которая не работает:

Вызов memset для установки всего объекта на ноль не пройдет. Во-первых, это вызовет много проблем, если ваша функция имеет одну или несколько виртуальных функций, а во-вторых, нулевой указатель не обязательно будет представлен битовой комбинацией всех нулей.

Что бы я, вероятно, сделал в вашем случае - это сохранить указатели в массиве или векторе Затем вы можете использовать функцию std::fill, чтобы установить их все в NULL. (Или вы можете использовать цикл, если хотите)

Конечно, если вам нужно делать это достаточно часто, возможно, стоит написать класс-обертку, который ведет себя как указатель, но устанавливает его в NULL в своем конструкторе по умолчанию.

Или вы можете использовать boost :: option, который работает по сути так. (хотя это не специфично для указателей)

2 голосов
/ 20 июня 2009

Почему бы не использовать конструктор по умолчанию:

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

}

Вы также можете сделать:

ptr1 = ptr2 = ptr3 = NULL;
1 голос
/ 20 июня 2009

Вы можете поместить указатели в структуру, а затем memset () структуру, когда это необходимо. Указатели все еще разделены, но у вас есть возможность нацелить их как единое целое, не затрагивая остальную часть вашего класса. Например:

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

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

void SomeClass::MakePtrNull()
{
    memset(&ptrs, 0, sizeof(ptrs));
}
0 голосов
/ 20 июня 2009

Используйте вектор для этого (потому что по звукам этого вам не нужно когда-либо редактировать список в будущем - и вам нужен произвольный доступ). Вы можете сделать это так:

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

Хотя, честно говоря, это пахнет гетто. Вы уверены, что ваша проблема требует этого решения? Если вы подробнее остановитесь на своей конкретной проблеме, возможно, в другом вопросе, я уверен, что вы сможете получить более точный ответ о том, как выполнить то, что вам нужно, более элегантно - вместо создания второй проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...