Вектор-член объектов (не указателей) сбрасывается после того, как указатель на (глобальный / постоянный) объект выходит из области видимости

#c #pointers #vector #parameter-passing #visibility

#c #указатели #вектор #передача параметров #видимость

Вопрос:

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

Участники:

     std::vector<cHasAMyClass>   collected;
    std::vector<cHasACHasAMyClass>  memberVector;//Actually an array of vectors, but simpler not to be.
 

конструктор внутреннего / локального класса:

     cHasACHasAMyClass(cHasAMyClass *ptrToCHasAMyC, int stuff) :
                masterRef(ptrToCHasAMyC),
                other_stuff(stuff) {}
 

метод, который я использовал:

 cHasAMyClass *firstUniqueOccurrence(std::vector<cHasAMyClass> *masterList, myClass *qSq) {
    for (int i = 0; i < (int)masterList->size();   i)
        if ((*masterList)[i].myClassPtr == qSq) return amp;((*masterList)[i]);
    masterList->push_back(cHasAMyClass(qSq));
    return amp;(masterList->back());
}
 

, который вызывает указанный выше метод:

 {
    std::vector<myClass *> allAtLoc;
    if (map->getAllHere(curLoc, amp;allAtLoc)) {
        for (int i = 0; i < (int)allAtLoc.size();   i) {
            int stuff = 42; //Or otherwise
            cHasAMyClass *newContainer = firstUniqueOccurrence(amp;(collected), allAtLoc[i]);
            memberVector.push_back(cHasACHasAMyClass(newContainer, stuff));
        }
    }
    allAtLoc.clear();
}
 

Проблема в том, что некоторое время спустя (обычно сразу после выхода из вышеуказанного блока) memberVector[0].masterRef появляется ошибка, которую я обнаруживаю (помимо сбоя), потому что его член типа myClass недопустим или равен нулю. Я думал, что установил для него указатель на сохраняющийся объект (управляемый в другой структуре данных, простой массив (/ ptr — это new / malloc ‘d)), но я новичок в использовании векторов и не уверен, какую косвенность я наблюдал.

У меня есть allAtLoc и newContainer выходит за рамки, и хотя они являются всего лишь указателями на объекты, у них есть побочные эффекты. Кстати, мой collected вектор не содержит ошибок.

Все это работало нормально до того, как я перешел на std::vector s, я не понимаю, как моя косвенность неверна, пожалуйста, может кто-нибудь посоветовать?

Комментарии:

1. можете ли вы показать рабочий код перед векторами? поможет обнаружить любые неправильные преобразования.

2. есть только код для myClass **map->getAllHere( сохранения в этом источнике, мне нужно будет выполнить поиск в более ранних архивах для альтернативного кода выше…

Ответ №1:

Трудно читать ваш код, но похоже, что вы берете указатели на элементы внутри a vector . Указатели, итераторы и ссылки на a vector становятся недействительными при изменении его емкости. Это может произойти как побочный эффект любой функции, которая вставляется в vector , поскольку создается новый больший внутренний массив, в который копируется текущее содержимое.

Если вы хотите использовать указатели на элементы в a vector , вы должны убедиться, что они не будут признаны недействительными. Если вы знаете количество элементов, вы можете вызвать reserve его перед вставкой любых элементов.

Комментарии:

1. Элементы сохраняются с использованием стандартного указателя на new общую выделенную память, как только что добавлено в моем обновлении. Ах, теперь я понимаю, что вы имеете в виду, вызов masterList->push_back аннулирует любые ссылки, которые я, возможно, ранее сделал для него! vector в конце концов, это не такая уж экономия труда! Я наблюдал в основном повреждение первых элементов, что немного странно, поскольку я ожидал, что память останется непрерывной. Однако мне нужно было бы лучше проверить наличие более тонких повреждений.

2. @John: Именно потому, что память остается непрерывной, указатели становятся недействительными.

3. да, но разве это не приведет к аннулированию всех смежных элементов, я нашел {bad line= 0, ok line= 1,2,4,5,6 ok bad line = 3}, но я не проверял все это тщательно. Поскольку я не знаю размер, вы предлагаете мне вернуться к new указателям и?

4. @John: Когда указатели, ссылки и итераторы признаются недействительными, это документируется и гарантируется стандартом. Проведите некоторое исследование по этому вопросу. Если используется vector для замены массива в стиле C, просто вызовите reserve(size) его после его инициализации.