С ++ глубоко инициализирует членов класса? - PullRequest
2 голосов
/ 05 февраля 2009

У меня есть класс в C ++ со следующим членом:

map< someEnum, vector<SomeObject*>* > someMap

Итак, у меня есть карта, которая дает мне вектор объектов для каждого перечисления, которое у меня есть. Я не могу понять, как C ++ инициализирует эти объекты. Глубоко ли инициализирует их по умолчанию? Если нет, что мне нужно делать?

Я получаю ошибки сегментации независимо от того, как я пытаюсь это сделать (и я пробовал все ), поэтому я предполагаю, что что-то упустил концептуально.


Должен отметить, что я пытался использовать:
map< someEnum, vector<SomeObject*> > someMap

также, и это не сработало. В этом случае, C ++ глубоко инициализирует вектор?

Ответы [ 4 ]

7 голосов
/ 05 февраля 2009

Правило таково: если контейнер STL содержит указатели на объекты , он не создает объекты в куче и назначает их этим указателям. Однако, если он содержит объектов , он вызывает конструктор по умолчанию для каждого содержащегося в нем объекта и таким образом инициализирует их.

Здесь у вас есть карта, содержащая указатели (независимо от того, какого рода). Так что не ожидайте, что карта заставит эти указатели указывать на память.

3 голосов
/ 05 февраля 2009

Похоже, карта дает вам указатель на вектор объектов. Если вы попытаетесь использовать карту через

mymap[MY_ENUM]->push_back(whatever);

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

mymap[MY_ENUM] = new vector<SomeObject*>;

или, намного лучше, просто сделайте карту простой вектором

map <someEnum, vector<SomeObject*> > mymap;

При первом вызове mymap[MY_ENUM] вектор будет инициализирован по умолчанию (с нулевым размером). Проблема в том, что вы пытаетесь использовать записи вектора перед его увеличением, например,

mymap[MY_ENUM][2] = whatever;

Вам все еще нужно использовать push_back или resize, или что-то, что дает вам место.

2 голосов
/ 05 февраля 2009

Вы не получите, чтобы векторные указатели SomeObject были аккуратно скрыты внутри этой карты, просто объявив объект.

Вместо этого вам придется действовать следующим образом:

map< someEnum, vector< SomeObject* >* > someMap;

someMap [ somevalue ] = new vector< SomeObject* >;

someMap [ somevalue ] -> push_back( new SomeObject );

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

// Untested code, may not even compile.
for( map< someEnum, vector< SomeObject* >* >::iterator iter = someMap.begin( ) ; iter != someMap.end( ) ; ++i )
{
     for( vector< SomeObject* >::iterator v = iter -> second -> begin( ) ; v != iter -> second -> end( ) ; ++v )
         delete *v;

     delete iter -> second;
}
1 голос
/ 05 февраля 2009

Вы получите пустую карту, которая может хранить std :: vector *, на которую ссылается someEnum. Пустая карта не будет содержать векторов. Вам нужно создать новый векторный объект (с новым - самый безопасный способ) и сохранить его указатель на карте.

Это может быть придирчиво, но если перечисления имеют фиксированный (маленький) размер, тогда зачем им карта? Простой массив будет легче разобраться с вашей лапшой и, вероятно, будет занимать больше места и потреблять больше ресурсов процессора, если у вас мало людей.

C ++ не может инициализировать содержимое карты или векторов, потому что он не знает, что вы хотите сохранить там.

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