почему бы не реализовать c ++ std :: vector :: pop_front (), сместив указатель на вектор [0]? - PullRequest
6 голосов
/ 31 января 2012

Почему pop_front() нельзя реализовать для векторов C ++, просто сместив указатель, содержащийся в имени вектора, на одну точку? Таким образом, в векторе, содержащем массив foo, foo является указателем на foo[0], поэтому pop_front() сделает указатель foo = foo[1], а оператор скобок просто выполнит обычную математическую обработку указателя. Это как-то связано с тем, как C ++ отслеживает объем используемой памяти, для чего, когда он выделяет пространство для массива?

Это похоже на другие вопросы, которые я видел о том, почему std::vector не имеет функции pop_front(), я признаю, но у меня нет никого, спрашивающего, почему вы не можете сдвинуть указатель.

Ответы [ 7 ]

2 голосов
/ 31 января 2012

Я начал печатать подробный ответ, объясняющий, как распределяется и освобождается память, но после того, как все это напечатал, я понял, что одни только проблемы с памятью не оправдывают, почему pop_front нет, как предлагали другие ответы.

Наличие pop_front в векторе, где дополнительная стоимость является еще одним указателем, в большинстве случаев оправданно.Проблема, на мой взгляд, push_front.Если контейнер имеет pop_front, то он также должен иметь push_front, в противном случае контейнер не согласован.push_front определенно дорого для векторного контейнера (если вы не сопоставите свои push с вашими pop с, что не является хорошим дизайном).Без push_front вектор действительно тратит память, если выполняется много операций pop_front без функциональности push_front.

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

2 голосов
/ 31 января 2012

vector не сможет освободить свою память, если он это сделает.

Как правило, вы хотите, чтобы накладные расходы на vector объект были маленькими.Это означает, что вы храните только три элемента: указатель на первый элемент, емкость и длину.

Чтобы реализовать то, что вы предлагаете, каждый vector когда-либо ( все изим) потребуется дополнительная переменная-член: смещение от начального указателя, в котором находится нулевой элемент.В противном случае память не могла бы быть освобождена, так как оригинальный дескриптор был бы потерян.

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

2 голосов
/ 31 января 2012

Потому что разработчики хотят оптимизировать размер вектора. Обычно они используют 3 указателя, один для начала, один для емкости (выделенный конец) и один для конца.

Выполнение того, что вам требуется, добавляет еще 4 байта к каждому вектору (а их так много в программе на c ++), что дает очень мало преимуществ: контракт вектора должен быть быстрым, когда отодвигаются новые элементы, удаляются и вставляются «Необычные» операции и их производительность имеют значение меньше размера класса.

1 голос
/ 31 января 2012

Вы можете использовать std::deque вместо std::vector.Это двусторонняя очередь с векторными элементами доступа.Он реализует как передний, так и задний push / pop.

http://www.cplusplus.com/reference/stl/deque/

1 голос
/ 31 января 2012

Вы могли бы сделать это, но vector разработан как простой контейнер с постоянным поиском по индексу времени и push / pop с конца.Выполнение того, что вы предлагаете, усложнит реализацию, так как придется отслеживать назначенное начало и «текущее» начало.Не говоря уже о том, что вы все еще не можете гарантировать постоянное время вставки спереди, но вы можете получить его иногда.

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

1 голос
/ 31 января 2012

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

0 голосов
/ 31 января 2012

Еще одним недостатком вашего предложения является то, что вы будете тратить пространство памяти, так как вы не сможете использовать их слева от массива после сдвига.Чем больше вы выполняете pop_front(), тем больше вы тратите впустую, пока вектор не будет разрушен.

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