2010-11-18 6 views
10

He estado programando en C++ durante bastante tiempo, pero de vez en cuando me topa con un fragmento de código usando STL que me hubiera llevado bastante tiempo y mucho más código para lograr.¿Cuál es tu truco de STL favorito?

STL lleva bastante tiempo acostumbrarse, y no hay muchos recursos con ejemplos de la vida real sobre cómo usarlo. Por favor comparte tu función STL favorita conmigo!

+0

¿Cuál es tu pregunta? Necesita ser CW? –

+1

¿Además de no usarlo? – mmmmmmmm

+1

@Paul: la pregunta está en el título. – sbi

Respuesta

11

dos2unix.cpp

#include <fstream> 
#include <iterator> 
#include <algorithm> 

bool is_cr(char c) { return c == '\r'; } 

int main(int, char* a[]) 
{ 
    std::ifstream is("/dev/stdin"); 
    std::ofstream os("/dev/stdout"); 
    std::istreambuf_iterator<char> in(is), end; 
    std::ostreambuf_iterator<char> out(os); 
    remove_copy_if(in, end, out, is_cr); 
} 
+2

¿No podría hacer también: 'remove_copy (in, end, out, '\ r')' y evitar tener que definir 'is_cr()'? –

+1

Es más una demostración de las características de STL que el dos2unix más pequeño. También podría usar std :: cout/cin sin mostrar cómo funciona con los archivos normales. – chris

14

Borrado de ciertos elementos de un vector en tiempo lineal con el borrado-remove-idioma:

vec.erase(std::remove(vec.begin(), vec.end(), is_odd), vec.end()); 

(bucle manualmente a través del vector y borrar en una por elemento sería tiempo cuadrático.)

+1

¡Un ejemplo de un functor! Bueno, más o menos ... –

+0

I # d up-vote su mención del idioma borrar-borrar, ¡pero me quedé sin votos! – sbi

+0

Otro truco horrible arreglado por lambdas. –

2

Contenedores, iteradores, al gorithms: todo lo bueno. Y no es realmente un truco, per se, pero para mí lo mejor de STL es functors. Los Iteradores pueden ser el pegamento que mantienen unido el motor STL, pero los funtores son el motor que lo hace Realmente le ahorran tiempo y escriben un mejor código. Que es, después de todo, de lo que trata el STL.

+0

+1 Me gustan los funtores. –

+0

Impresionante, es el peor absoluto. Terrible lugar, bien arreglado por lambdas. –

+0

@Hans: cuando dices "localidad", ¿te refieres a tener docenas de pequeños funtores salpicados por todas partes? –

7

Usando un vector para un búfer. En lugar de:

int size_needed = GetData(NULL, 0); 
char * buffer = new char[size_needed]; 
GetData(buffer, size_needed); 
... 
delete [] buffer; 

El uso de un vector:

int size_needed = GetData(NULL, 0); 
std::vector<char> buffer(size_needed); 
GetData(&buffer[0], size_needed); 
4

shared_ptr dentro de un shared_ptr.

A veces uso std :: shared_ptr custom destructor para implementar un método simple de fábrica agrupada. No sé si cuenta como un "truco".

class Factory 
{ 
    std::queue<std::shared_ptr<Type>> pool_; // Possibly tbb::concurrent_bounded_queue. Could also be contained as a shared_ptr to allow objects to outlive the factory. 
public: 
    std::shared_ptr<Type> create() 
    { 
     std::vector<Type> ptr; 
     if(pool.empty()) 
      ptr = std::make_shared<Type>(); 
     else 
     { 
      ptr = std::move(pool_.front()); 
      pool_.pop(); 
     } 

     return std::shared_ptr<Type>(ptr.get(), [=](Type*){pool_.push(ptr)};); // Put back into pool once destructed 
    } 
} 
+0

Creo que eso cuenta como un truco, muy elegante – Benj

8

Recuerdo una que me gustó mucho cuando me encontré sobre él (~ hace 10 años) en comp.lang.c++.moderated:

int main(int argc, char* argv[]) 
{ 
    std::vector arguments(argv+1, argv+argc); 
    // whatever 
} 

Hoy en día, yo no uso esto. ¿Por qué poner las cosas en un vector, que luego procesas por iteradores, cuando ya tienes iteradores para empezar? Esto ahora no se refiere tanto al TEL como una colección de contenedores y algoritmos, pero más la idea que nos trajo de pegar secuencias y algoritmos por los iteradores:

template<typename It> 
int process_arguments(It begin, It end) 
{ 
    // whatever we need to do with those arguments... 
} 

int main(int argc, char* argv[]) 
{ 
    return process_arguments(argv+1, argv+argc); 
} 

(Sí, muy a menudo escribo pequeña consola utilidades.)

+1

Probablemente quiso decir 'std :: vector some_cool_variable_name (argv + 1, argv + argc); ¿verdad? Porque de lo contrario es un vector temporal que muere en el punto y coma. – fredoverflow

+1

@Fred: '' – sbi

4

Lo que más me gusta es usar el STL para hacer una codificación de estilo funcional.Por ejemplo, contando los elementos más pequeños que 2:

n = std::count_if(v.begin(), v.end(), std::bind2nd(std::less<int>(), 2)); 
+1

Puede reducir 'std :: bind2nd (std :: less (), 2)' a '_1 <2' con' boost :: lambda' :) – fredoverflow

+4

@Fred: Por supuesto. La pregunta original era sobre el STL, no impulsar ... :) –

3

No es especialmente útil, pero me gusta fingiendo std::iota (donde C++ 0x no está disponible) con una llamada a std::partial_sum:

std::vector<int> v(5, 1); // 1, 1, 1, 1, 1 
    partial_sum(v.begin(), v.end(), v.begin()); // 1, 2, 3, 4, 5 

Como por algo que he utilizado realmente en el código de producción: prueba si dos archivos son idénticos:

if(equal(std::istreambuf_iterator<char>(file1), 
      std::istreambuf_iterator<char>(), 
      std::istreambuf_iterator<char>(file2))) 
    { // files are equal, do whatever 

en general, creo que partial_sum y inner_product merecen mucho más amor de lo que ven. Con funtores suficientemente inteligentes pueden hacer grandes cosas.

3

Mi truco favorito STL es evitar el uso de

  • la CRT
  • punteros primas (C++ 0x).

La expresividad del código STL frente al equivalente de fuerza bruta es sorprendente.

Cuestiones relacionadas