2010-11-18 9 views
10

I już zostały programowania w języku C++ na dłuższą chwilę teraz, ale co jakiś czas, a potem natknąć fragmentu kodu przy użyciu STL, które podjęły sobie sporo czasu i dużo więcej kodu do wykonania.Jaka jest twoja ulubiona sztuczka STL?

STL zajmuje sporo czasu, aby się do tego przyzwyczaić, a nie ma tam zbyt wielu zasobów z przykładami, jak z niego korzystać. Proszę, podziel się ze mną swoją ulubioną funkcją STL!

+0

Jakie jest twoje pytanie? Musi być CW? –

+1

Oprócz tego, że go nie używasz? – mmmmmmmm

+1

@Paul: Pytanie jest w tytule. – sbi

Odpowiedz

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

Nie możesz również zrobić: 'remove_copy (in, end, out, '\ r')' i uniknąć konieczności definiowania 'is_cr()'? –

+1

To jest bardziej demonstracja funkcji STL niż najmniejszy dos2unix. Mogłabym też użyć std :: cout/cin bez pokazywania, jak to działa, używając zwykłych plików. – chris

14

usuwanie pewnych elementów z wektorem czasie liniowej z wymazaniem remove-idiomu:

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

(ręcznie przelotowego wektora i jego usuwanie na zasadzie w przeliczeniu na element będzie wynosić czas kwadratowy.)

+1

Przykład funktora! No cóż, mniej więcej ... –

+0

Wrzucam do góry twoją wzmiankę o wymazaniu-usunięciu idiomu, ale zabrakło mi głosów! – sbi

+0

Kolejna okropna sztuczka naprawiona przez lambdasa. –

2

Kontenery, iteratory, al gorithms: wszystkie dobre rzeczy. I to naprawdę nie jest sztuczka, per se, ale dla mnie najlepszą rzeczą w STL jest functors. Iteratory mogą być klejem, który trzyma razem samochód STL, ale funktory są silnikiem, który sprawia, że ​​jest on naprawdę oszczędny i lepiej napisać kod. W końcu to jest to, o czym jest STL.

+0

+1 Lubię funktory. –

+0

Oszałamiająca, jest absolutnie najgorsza. Okropna miejscowość, ładnie naprawiona przez lambdas. –

+0

@Hans: Kiedy mówisz "miejscowość", masz na myśli to, że dziesiątki małych funktorów rozsypuje się wszędzie? –

7

Stosując wektor do bufora. Zamiast:

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

Stosując wektor:

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

shared_ptr wewnątrz shared_ptr.

Czasami używam niestandardowego destruktora std :: shared_ptr, aby zaimplementować prostą metodę wspólnej puli. Dunno, jeśli liczy się jako "trik".

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

Myślę, że liczy się to jako podstęp, bardzo elegancki – Benj

8

Pamiętam, że bardzo lubiłem, kiedy natknął się nad nim (~ 10 lat temu) w comp.lang.c++.moderated:

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

Dzisiaj, nie używam już tego. Po co umieszczać materiał w wektorze, który następnie przetwarza się za pomocą iteratorów, skoro na początku są już iteratory? To już nie dotyczy tyle STL jako zbiór pojemników i algorytmów, ale pomysł przyniósł na nas klejenia sekwencje i algorytmy przez iteratory:

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

(Tak, dość często pisać małą konsolę narzędzia.)

+1

Prawdopodobnie miałeś na myśli 'std :: vector some_cool_variable_name (argv + 1, argv + argc); prawda? Ponieważ w przeciwnym razie jest to tymczasowy wektor, który umiera na średniku. – fredoverflow

+1

@Fred: '@ 003: – sbi

4

Najbardziej podoba mi się używanie STL do kodowania w stylu funkcjonalnym.Na przykład, licząc elementy mniejsze niż 2:

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

Możesz zredukować' std :: bind2nd (std :: less (), 2) 'do' _1 <2' z 'boost :: lambda' :) – fredoverflow

+4

@Fred: Oczywiście. Pierwotne pytanie dotyczyło STL, a nie doładowania ... :) –

3

Nie jest szczególnie użyteczny, ale I jak udaje std::iota (gdzie C++ 0x nie jest dostępny) o wywołaniu 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 

As coś mam faktycznie używane w kodzie produkcji: testowanie czy dwa pliki są identyczne:

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

ogólnie myślę partial_sum i inner_product zasługują na dużo więcej miłości, niż widzą. Przy wystarczająco inteligentnych funktorach potrafią robić wspaniałe rzeczy.

3

Mój ulubiony trik STL jest unikanie używania

  • CRT
  • surowe wskaźniki (C++ 0x).

Ekspresyjność kodu STL kontra ekwiwalent brutalnej siły jest niesamowita.

Powiązane problemy