2010-12-03 5 views
11

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

#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); 
} 

ответ

9

Да.

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 гарантируется непрерывным должно быть п o проблема.

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

+1

+1 Вы могли бы просто отредактировать удаленный ответ и восстановить его. – 2010-12-03 13:44:35

+0

Я вижу, сделаю это в будущем. – ronag 2010-12-03 13:46:10

+2

Это вопрос любопытства ... не настоящий код :) – 2010-12-03 13:46:12

-2

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

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

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

Использование std::stack только для бондажа

2

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

1

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

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

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

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

1

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

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

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

5

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

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