Подтвердить что ты не робот

Что такое конструктор по умолчанию для указателя на С++?

У меня такой код:

class MapIndex
{
private:
    typedef std::map<std::string, MapIndex*> Container;
    Container mapM;

public:
    void add(std::list<std::string>& values)
    {
        if (values.empty()) // sanity check
            return;

        std::string s(*(values.begin()));
        values.erase(values.begin());
        if (values.empty())
            return;

        MapIndex *mi = mapM[s];  // <- question about this line
        if (!mi)
            mi = new MapIndex();
        mi->add(values);
    }
}

Основная проблема, которую я испытываю, заключается в том, будет ли выражение mapM [s] возвращать ссылку на NULL-указатель, если новый элемент будет добавлен на карту?

SGI docs говорят об этом: data_type & operator [] (const key_type & k) Возвращает ссылку на объект, связанный с определенным ключом. Если в карте нет такого объекта, оператор [] вставляет объект по умолчанию data_type().

Итак, мой вопрос заключается в том, будет ли вставка объекта по умолчанию data_type() создать указатель NULL или создать недопустимый указатель, указывающий где-нибудь в памяти?

4b9b3361

Ответ 1

Он создаст указатель NULL (0), который в любом случае является недопустимым указателем:)

Ответ 2

Да, он должен быть нулевым (NULL) указателем, поскольку контейнеры stl будут инициализировать объекты по умолчанию, если они явно не сохранены (т.е. доступ к несуществующему ключу на карте по мере того, как вы делаете или изменяете размер вектора в большем размере).

Стандарт С++, пункт 8.5 пункта 5:

По умолчанию инициализируется объект тип T означает:

  • Если T - тип класса не-POD (класс предложения), значение по умолчанию конструктор для T называется (и инициализация плохо сформирована, если T имеет нет доступного конструктора по умолчанию)
  • Если T - тип массива, каждый элемент инициализируется по умолчанию
  • В противном случае хранилище для объекта iszero-initialized.

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

int a; // not default constructed, will have random data 
int b = int(); // will be initialised to zero

Ответ 3

ОБНОВЛЕНИЕ: Я завершил свою программу, и эта строка, о которой я спрашивал, вызывает ее иногда, но на более позднем этапе. Проблема в том, что я создаю новый объект без изменения указателя, хранящегося в std:: map. То, что действительно необходимо, является ссылкой или указателем на этот указатель.

MapIndex *mi = mapM[s];  // <- question about this line
if (!mi)
    mi = new MapIndex();
mi->add(values);

следует изменить на:

MapIndex* &mi = mapM[s];  // <- question about this line
if (!mi)
    mi = new MapIndex();
mi->add(values);

Я удивлен, что никто этого не заметил.

Ответ 4

Выражение data_type() оценивается объектом, инициализированным по умолчанию. В случае не-POD-типов вызывается конструктор по умолчанию, но в случае типов POD, таких как указатели, инициализация по умолчанию эквивалентна нулевой инициализации.

Итак, вы можете положиться на свою карту, создав указатель NULL. Для объяснения вы можете обратиться к Инициализаторы псевдоконструктора.

Ответ 5

Не уверен в сбое, но определенно утечка памяти, как это утверждение

если (! mi)   mi = new MapIndex();

всегда возвращает true, потому что указатель mi не ссылается на то, что mapM удерживает для частного значения s.

Я бы также избегал использования обычных указателей и использовал boost:: shared_ptr или некоторые другой указатель, который освобождает память при уничтожении. Это позволяет вызвать mapM.clear() или стереть() который должен вызывать деструкторы ключей и значений, хранящихся на карте. Ну, если значение POD, например, ваш указатель, тогда никакой деструктор не вызывается для этого, если только ручное удаление в то время как повторение всей карты приведет к утечке памяти.