2014-06-20 4 views
0

Я думаю о том, чтобы сделать структуру векторных данных более эффективной.Создание вектора более эффективно при добавлении элементов

Предположим, что это для некоторого общего типа данных T ... тогда, добавив новый элемент к вектору, то, что текущий std :: vector делает, - это перераспределить весь новый кусок памяти из n + 1 элементов.

Что я хочу сделать ...

Я написал небольшую программу:

#include<iostream> 

using namespace std; 

int main() 
{ 

    int *i,*j; 
    i=new int; 
    cout<<i; 
    delete i; 
    j=new int ; 
    cout<<j; 
    delete j; 

     return 0; 
} 

Оба места памяти были те же ...

Что теперь я имею в виду, что первый я буду выделять память для общих типов данных следующим образом:

T *temp=new T; 

Теперь сравните адрес памяти временного номера на адрес последнего элемента вектора .... Если они отличаются на sizeof (T), тогда я добавлю новый элемент там сам .... иначе сделайте это так std::vector делает это ....

Таким образом, это уменьшает затраты на копирование всех элементов ... если данные большие, то это может значительно изменить ...... !!

Pls скажите мне, если я нахожусь на правильном пути ...

+3

Векторы не могут делать то, что вы описали, потому что это заставит 'push_back' не выполнять свою амортизированную постоянную временную сложность. Векторы довольно эффективны, особенно с C++ 11, где элементы можно перемещать, а не копировать при перераспределении. Кроме того, ваши трюки с адресным адресом памяти никоим образом не гарантированы, поэтому нет, это не будет работать в переносном режиме. – chris

+3

['std :: vector :: reserve'] (http://en.cppreference.com/w/cpp/container/vector/reserve) – BoBTFish

+0

Нет ... я пробовал это с моей собственной реализацией вектора. операция удаления будет иметь постоянную временную сложность ... что я делаю, только если достаточно пространства, прилегающего к последнему элементу вектора, я говорю не копировать все материалы в diff. местоположение, но выделить его рядом с самим последним элементом .... – PRP

ответ

2

Я понимаю вашу мысль, как

Если new возвращает мне адрес, который является смежным с памятью уже проведенного MyVector объект, я просто использую его без перераспределения.

Да, это действительно может быть теоретически. Однако на практике невозможно получить такой смежный адрес, поскольку распределитель, скорее всего, сохранит некоторые внутренние данные в начале выделенного им блока (например, его размер или указатель на следующий блок или что-то еще).

Точные данные зависят от распределителя, используемого вашей стандартной библиотекой (и всей операционной системы), но вот пример типичного поведения. Вы звоните new T, где sizeof(T) - 16 (например). operator new вызывает malloc внутренне, который вызывает функцию выделения ОС. Эта функция выделяет 20 байт памяти по адресу X. Он хранит «16» в первых 4 байтах по адресу X и возвращает адрес X + 4 в malloc, который, в свою очередь, возвращает его operator new и к вашему приложению. Таким образом, вы никогда не сможете получить непрерывную память.

+0

yeahhh .... я читал о работе malloc ... вы правы ... !! Дин перекрестите мой разум, думая о такой сумасшедшей идее .... ответ будет принят ... – PRP

+0

Еще одна идея перешла Мой разум .... Я сделал несколько экспериментов с тем, как malloc выделяет память ... код выше i написали, проверит, доступна ли память или нет .... теперь, если память доступна, то ... что я буду делать, это перейти в память, где malloc хранит свои «метаданные» и модифицировать ее так, чтобы она думала что он выделил больше памяти, чем это было на самом деле ..... и поэтому эффективный вектор может быть реализован .... – PRP

+0

@PRP И что, если эта «большая память», которую вы фиктивно заявляете, уже занята чем-то? Кроме того, ваш код будет тесно связан с конкретной реализацией 'malloc', на котором вы это делаете. И вообще, сложность в маленьких случаях не имеет значения. И сложность больших случаев в 'std :: vector' уже амортизирована постоянной. Это так плохо для вашего дела? – Angew

Смежные вопросы