2010-12-03 6 views
11

¿Está funcionando el siguiente código garantizado por el estándar (suponiendo que st no esté vacío)?Copie std :: stack en un estándar :: 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); 
} 

Respuesta

9

Sí.

std::stack es solo un adaptador de contenedor.

Se puede ver que en realidad es .top() (§23.3.5.3.1)

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

Dónde c es el contenedor, que en este caso es un std::vector

Lo que significa que su código es básicamente traducirse en:

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

Y como std::vector se garantiza que sea continua no debe haber n o problema

Sin embargo, eso no significa que sea una buena idea. Si necesita usar "hacks" como este, generalmente es un indicador de mal diseño. Probablemente desee utilizar std::vector desde el principio.

+1

+1 podrías haber editado tu respuesta eliminada y haberla recuperado. –

+0

Ya veo, haremos eso en el futuro. – ronag

+2

Esta es una pregunta de curiosidad ... código no real :) –

-2

Editar: instrucción inicial redactada, el estándar realmente proporciona una definición completa para el adaptador de pila, no queda nada para los implementadores. ver la respuesta superior.

Desea un contenedor que tenga un método push y pop y le permita inspeccionar elementos en cualquier parte del contenedor y use un std::vector para el almacenamiento. Hay un contenedor de este tipo en la biblioteca de plantillas estándar

se llama std::vector.

Uso std::stack sólo con fines de servidumbre

2

Sí, está garantizado. Los vectores están garantizados para usar almacenamiento contiguo, por lo que su código funcionará. Sin embargo, es un poco complicado, y si alguien cambia el tipo de contenedor subyacente de la pila, su código continuará compilando sin errores, pero el comportamiento en tiempo de ejecución se romperá.

1

no tengo una referencia a la norma que apoyen esta desgracia, pero no hay muchas maneras en las que podría salir mal supongo:

  • Especificación std::vector<int> como el tipo de contenedor significa que los elementos deben almacenarse en un std::vector<int>.
  • st.top() debe devolver una referencia a un elemento en el recipiente subyacente (es decir, un elemento en el std::vector<int>. Dado que los requisitos sobre el recipiente son que soporta back(), push_back() y pop_back(), podemos suponer razonablemente que top() devuelve una referencia a la . último elemento en el vector
  • end por lo tanto, apunta a un más allá del último elemento
  • start por lo tanto, apunta al comienzo

Conclusión..: A menos que la suposición fuera incorrecta, debe funcionar.

EDITAR: Y dada la referencia de la otra respuesta al estándar, la suposición es correcta, por lo que funciona.

1

Según this page, std::stack utiliza una clase de contenedor para almacenar elementos.

Supongo que lo que sugiere funciona solo si el containter almacena sus elementos de forma lineal (std::vector).

Por defecto, std::stack usa un std::deque que, hasta donde yo sé, no cumple con este requisito. Pero si especifica un std::vector como una clase contenedor, no puedo ver una razón por la que no funcione.

+3

Es por eso que especificó 'std :: vector ' como el tipo de contenedor Supongo :) –

+0

@sgolodetz: Just realizó esto;) Todavía no estoy completamente despierto en este momento. – ereOn

+2

Para ser honesto, lo desnate la primera vez y casi lo extraño también ... –

5

Solo std::vector está garantizado por C++ 03 para tener elementos contiguos (23.4.1). En C++ 1x esto se extenderá también a std::string (defect #530).

+1

Guau, nunca supe que la cuerda no tenía tal garantía. Interesante, gracias. Voto ascendente, aunque esto es irrelevante para mi pregunta –

Cuestiones relacionadas