Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.09.2014, 17:55   #1
KemanSR
Форумчанин
 
Регистрация: 03.05.2010
Сообщений: 129
По умолчанию Как работает push_back контейнера vector?

Добрый день! Описываю дерево состоящее из
Код:
class CTNode{
// Ну тут внутренности
    CTNode* AddChild(CTNode* pnode);
    UINT m_iNumber;
    vector<CTNode> m_Children;
    CTNode* m_pPer;
};
Вот реализация добавления элемента:
Код:
CTNode* CTNode::AddChild(CTNode* pnode){
    pnode->m_pPer = this;
    m_Children.push_back(*pnode);
    return &m_Children.back();
}
После добавления некоторого количества записей данные в m_pPer меняются. Может ли контейнер перемещать элементы хранимые в нем самостоятельно, при добавлении очередного элемента (push_back)? Можно ли этого избежать?
KemanSR вне форума Ответить с цитированием
Старый 10.09.2014, 18:08   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

если ничего не удаляется или не инсертится то он сам порядок не меняет.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 10.09.2014, 18:15   #3
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию

Цитата:
Может ли контейнер перемещать элементы хранимые в нем самостоятельно, при добавлении очередного элемента
Самостоятельно не может. Если используется команда push_back, данные добавляются в "хвост" вектора. Если нужно вставить элемент в другое место, используется команда insert.
Порядок элементов может самостоятельно меняться только в ассоциативных контейнерах set, multiset и map, multimap при добывлении и удалении данных из контейнера.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder

Последний раз редактировалось Smitt&Wesson; 10.09.2014 в 18:18.
Smitt&Wesson вне форума Ответить с цитированием
Старый 10.09.2014, 18:16   #4
KemanSR
Форумчанин
 
Регистрация: 03.05.2010
Сообщений: 129
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
... не удаляется или не инсертится ...
А если пушбегится, есть ли вероятность что элементы меняют адрес? Могу я спросить Ваше дорогостоящее мнение по поводу метода AddChild, правильно ли он написан с точки зрения логики?
KemanSR вне форума Ответить с цитированием
Старый 10.09.2014, 18:29   #5
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию

Цитата:
А если пушбегится, есть ли вероятность что элементы меняют адрес?
Я уже выше написал - нет. При инсерте, данные вставляются именно в ту позицию, которую Вы указали. Все элементы со старшими адресами, сдвигаются вверх на одну позицию итератора.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Старый 10.09.2014, 18:29   #6
KemanSR
Форумчанин
 
Регистрация: 03.05.2010
Сообщений: 129
По умолчанию

На тот случай если кому, то не будет трудно помочь выложу код. Прошу простить, что MFC, вопрос изначально касался vector'a. Да я знаю, что контейнеры есть в MFC.

Ошибка возникает здесь:
Код:
void CTreeDoc::AddNode(){
    CTNode node;
    // Запись не заполнена
    if (!node.FillNode())// Здесь не может быть ошибки
        return;

    // Проверка нет ли в предках
    CTNode* pNode = m_pSel;
    while (pNode){
        if (pNode->m_iArt == node.m_iArt){
            AfxMessageBox(L"Указанный артикул встречается среди предков,\n"
                            L"либо у выделенного элемента. Введите другой.");
            return;
        }
        else{
            pNode = pNode->GetParent();
        }

    }

    // Проверка нет ли в потомках
    if (m_pSel->FindArt(node.m_iArt)){
        AfxMessageBox(L"Указанный артикул встречается,\n"
            L"среди потомков. Введите другой.");
        return;
    }


    AddNode(&node);

    UpdateAllViews(NULL);
}

Вот перегруженный метод:
Код:
void CTreeDoc::AddNode(CTNode* pNode)
{
    // Нет корня
    if (!m_pRoot){
        m_pRoot = m_pSel = new CTNode;
        m_pRoot->Duplicate(pNode);
        m_iNodeCount++;
        m_bModified = true;
    }
    else{
        // Запись выделена
        if (m_pSel){
            m_pSel = m_pSel->AddChild(pNode);
            m_iNodeCount++;
            m_bModified = true;
        }
    }

    CPoint min = m_P0;
    m_pRoot->SetPos(min.x, min.y);
}
KemanSR вне форума Ответить с цитированием
Старый 10.09.2014, 18:32   #7
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,543
По умолчанию

KemanSR, извините, я бы помог но сегодня с копки картошки вернулся, устал до чёртиков. На простые вопросы могу ответить, но в коде разбираться, уже сил нет.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Старый 10.09.2014, 19:16   #8
KemanSR
Форумчанин
 
Регистрация: 03.05.2010
Сообщений: 129
По умолчанию

Решил проверить Ваши ответы:
Код:
void f()
{
    struct strt{
        int i;
        strt* parent;
    };

    vector<strt> vec;
    const int count = 10000;
    strt* ar[count];
    strt* p = NULL;
    for (int i = 0; i < count; i++){
        strt s;
        s.i = i;
        s.parent = p;
        vec.push_back(s);
        ar[i] = p = &vec.back();
    }

    strt *p1, *p2;
    for (int i = 0; i < vec.size(); i++){
        p1 = &vec.at(i);
        p2 = ar[i];
        if (p1 != p2){
            AfxMessageBox(L"Not good");
            return;
        }
    }
    AfxMessageBox(L"Ok");
}
Выдает "Нот гуд". Прошу помочь.
KemanSR вне форума Ответить с цитированием
Старый 10.09.2014, 19:18   #9
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от KemanSR Посмотреть сообщение
Добрый день! Описываю дерево состоящее из
Код:
class CTNode{
// Ну тут внутренности
    CTNode* AddChild(CTNode* pnode);
    UINT m_iNumber;
    vector<CTNode> m_Children;
    CTNode* m_pPer;
};
Вот реализация добавления элемента:
Код:
CTNode* CTNode::AddChild(CTNode* pnode){
    pnode->m_pPer = this;
    m_Children.push_back(*pnode);
    return &m_Children.back();
}
После добавления некоторого количества записей данные в m_pPer меняются. Может ли контейнер перемещать элементы хранимые в нем самостоятельно, при добавлении очередного элемента (push_back)? Можно ли этого избежать?
Да может.
Нельзя закладываться на неизменность адрес объекта элемента вектора.

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

Поэтому, старый адрес элемента может стать невалидным.
_Bers вне форума Ответить с цитированием
Старый 10.09.2014, 19:26   #10
KemanSR
Форумчанин
 
Регистрация: 03.05.2010
Сообщений: 129
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Да может.
Нельзя закладываться на неизменность адрес объекта элемента вектора.

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

Поэтому, старый адрес элемента может стать невалидным.
Спасибо, я тоже на это грешил. В моем случае он сегментирует память - некоторые элементы лежат на прежних местах, некоторые перемещаются.
KemanSR вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
На основе контейнера vector построить двумерный динамический массив С++ Вероника99 Помощь студентам 1 25.05.2014 17:22
C++ Boost - vector<path> to vector<string> frommars Общие вопросы C/C++ 0 04.02.2013 21:19
Как вытащить строку из vector'a Tema_Crazzzy Общие вопросы C/C++ 2 12.09.2010 20:38
проблема с push_back torres Общие вопросы C/C++ 6 20.08.2010 15:27
Как программно удалить компонент от формы или другого компонента (контейнера)? SkAndrew Общие вопросы Delphi 3 27.05.2008 15:20