2008-10-06 18 views
9

¿Es posible crear un contenedor tipo STL, o incluso solo un iterador de estilo STL, para una matriz existente de elementos de tipo POD?STL envoltorio sin copia alrededor de una matriz existente?

Por ejemplo, supongamos que tengo una matriz de entradas. Sería conveniente poder llamar a algunas de las funciones de STL, como find _ if, contar _ if, o ordenar directamente en esta matriz.

Sin solución: copiar toda la matriz, o incluso solo referencias a los elementos. El objetivo es ahorrar mucha memoria y tiempo y, a la vez, permitir el uso de otros algoritmos STL.

+0

" Por ejemplo, supongamos que tengo una matriz de entradas. Sería conveniente poder llamar a algunas de las funciones de STL, como find_if, count_if, o ordenarlas directamente en esta matriz. " Puedes. Todas las anteriores. – moswald

Respuesta

22

Puede invocar muchos de los algoritmos de STL directamente en una matriz de estilo C normal; fueron diseñados para que funcionen. por ejemplo,:

int ary[100]; 
// init ... 

std::sort(ary, ary+100); // sorts the array 
std::find(ary, ary+100, pred); find some element 

Creo que encontrará que la mayoría de las cosas funcionan como cabría esperar.

+0

¡Es bueno saberlo! Gracias. – Tyler

4

Puede usar Boost.Array para crear un tipo de matriz C++ con semántica STL.

utilizando conjuntos:

int a[100]; 
for (int i = 0; i < 100; ++i) 
    a[i] = 0; 

utilizando boost.arrays:

boost::array<int,100> a; 
for (boost::array<int,100>::iterator i = a.begin(); i != a.end(); ++i) 
    *i = 0; 

Actualizar: con C++ 11, ahora se puede utilizar std::array.

+1

boost.array no es copia cero – Bklyn

+2

No quise copiarlo en un boost.array sino usar un boost.array como su objeto original. – Ferruccio

5

Todos los algoritmos STL usan iteradores.
Un puntero es un iterador válido en una matriz de objetos.

N.B. El iterador final debe ser un elemento más allá del final de la matriz. De ahí los datos + 5 en el siguiente código.

#include <algorithm> 
#include <iostream> 
#include <iterator> 

int main() 
{ 
    int data[] = {4,3,7,5,8}; 
    std::sort(data,data+5); 

    std::copy(data,data+5,std::ostream_iterator<int>(std::cout,"\t")); 
} 
2

Un puntero es un modelo válido de un iterador:

struct Bob 
{ int val; }; 

bool operator<(const Bob& lhs, const Bob& rhs) 
{ return lhs.val < rhs.val; } 

// let's do a reverse sort 
bool pred(const Bob& lhs, const Bob& rhs) 
{ return lhs.val > rhs.val; } 

bool isBobNumberTwo(const Bob& bob) { return bob.val == 2; } 

int main() 
{ 
    Bob bobs[4]; // ok, so we have 4 bobs! 
    const size_t size = sizeof(bobs)/sizeof(Bob); 
    bobs[0].val = 1; bobs[1].val = 4; bobs[2].val = 2; bobs[3].val = 3; 

    // sort using std::less<Bob> wich uses operator < 
    std::sort(bobs, bobs + size); 
    std::cout << bobs[0].val << std::endl; 
    std::cout << bobs[1].val << std::endl; 
    std::cout << bobs[2].val << std::endl; 
    std::cout << bobs[3].val << std::endl; 

    // sort using pred 
    std::sort(bobs, bobs + size, pred); 
    std::cout << bobs[0].val << std::endl; 
    std::cout << bobs[1].val << std::endl; 
    std::cout << bobs[2].val << std::endl; 
    std::cout << bobs[3].val << std::endl; 

    //Let's find Bob number 2 
    Bob* bob = std::find_if(bobs, bobs + size, isBobNumberTwo); 
    if (bob->val == 2) 
     std::cout << "Ok, found the right one!\n"; 
    else 
     std::cout << "Whoops!\n"; 

    return 0; 
} 
5

Puede utilizar una plantilla de función en línea de modo que usted no tiene que duplicar el índice de matriz

template <typename T, int I> 
inline T * array_begin (T (&t)[I]) 
{ 
    return t; 
} 

template <typename T, int I> 
inline T * array_end (T (&t)[I]) 
{ 
    return t + I; 
} 

void foo() 
{ 
    int array[100]; 
    std::find (array_begin (array) 
     , array_end (array) 
     , 10); 
} 
Cuestiones relacionadas