Скопируйте std:: stack в std::vector

Является ли следующий код гарантированным стандартом для работы (если st не пуст)?

#include <vector>
#include <stack>
int main()
{
   extern std::stack<int, std::vector<int> > st;
   int* end   = &st.top() + 1;
   int* begin = end - st.size();
   std::vector<int> stack_contents(begin, end);
}

Ответ 1

Да.

std::stack - это только контейнерный адаптер.

Вы можете видеть, что .top() на самом деле (§23.3.5.3.1)

reference top() { return c.back(); }

Где c - контейнер, который в этом случае является std::vector

Это означает, что ваш код в основном переведен на:

   extern std::vector<int> st;
   int* end   = &st.back() + 1;
   int* begin = end - st.size();
   std::vector<int> stack_contents(begin, end);

И поскольку std::vector гарантированно будет непрерывным, проблем не должно быть.

Однако это не означает, что это хорошая идея. Если вам нужно использовать "хаки", как это, это обычно показатель плохой конструкции. Вероятно, вы хотите использовать std::vector с самого начала.

Ответ 2

Только std::vector гарантируется С++ 03, чтобы иметь смежные элементы (23.4.1). В С++ 1x это будет также распространено на std::string (дефект # 530).

Ответ 3

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

Ответ 4

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

  • Указание std::vector<int> в качестве типа контейнера означает, что элементы должны храниться в std::vector<int>.
  • st.top() должен возвращать ссылку на элемент в базовом контейнере (т.е. элемент в std::vector<int>. Поскольку требования к контейнеру состоят в том, что он поддерживает back(), push_back() и pop_back(), мы может разумно предположить, что top() возвращает ссылку на последний элемент в векторе.
  • end поэтому указывает на один последний элемент.
  • start поэтому указывает на начало.

Заключение: если это предположение не так, оно должно работать.

РЕДАКТИРОВАТЬ: И учитывая другую ответную ссылку на стандарт, предположение верно, поэтому оно работает.

Ответ 5

Согласно эта страница, std::stack использует класс контейнера для хранения элементов.

Я предполагаю, что вы предлагаете работать только в том случае, если сдерживатель сохраняет свои элементы линейным способом (std::vector).

По умолчанию std::stack использует std::deque, который, насколько мне известно, не соответствует этому требованию. Но если вы укажете std::vector как класс контейнера, я не вижу причины, по которой он не работает.

Ответ 6

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

Вам нужен контейнер с методом push и pop и позволяет проверять элементы в любом месте контейнера и использовать std::vector для хранения. В стандартной библиотеке шаблонов есть такой контейнер

он называется std::vector.

Используйте std::stack только для целей рабства