开发者

What's your favorite STL trick? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center. Closed 12 years ago. 开发者_StackOverflow社区

I've been programming in C++ for quite a while now, but every now and then I stumble upon a code snippet using STL that would have taken myself quite some time and a lot more code to accomplish.

STL takes quite a while to get used to, and there are not many resources out there with real-life examples on how to use it. Please share your favorite STL feature with me!


Erasing certain elements from a vector in linear time with the erase-remove-idiom:

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

(Manually looping through the vector and erasing on a per-element basis would be quadratic time.)


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


I remember one that I really liked when I stumbled over it (~10 years ago) in comp.lang.c++.moderated:

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

Today, I don't use this anymore. Why put the stuff into a vector, which you then process by iterators, when you already have iterators to start with? This now doesn't concern so much the STL as a collection of containers and algorithms, but more the idea it brought upon us of gluing sequences and algorithms by iterators:

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

(Yes, I quite often write small console utilities.)


Using a vector for a buffer. Instead of:

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

Using a vector:

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


What I like the most is using the STL to do functional-style coding. For instance, counting the elements smaller than 2:

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


shared_ptr inside a shared_ptr.

I sometimes use std::shared_ptr custom destructor to implement a simple pooled factory method. Dunno if it counts as a "trick".

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


My favourite STL trick is avoiding usage of

  • the CRT
  • raw pointers (C++0x).

Expressiveness of STL code versus brute force equivalent is amazing.


Not particularly useful, but I like faking std::iota (where C++0x is not available) with a call to 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 for something I've actually used in production code: testing if two files are identical:

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

In general, I think partial_sum and inner_product deserve a lot more love than they see. With sufficiently smart functors they can do great things.


Containers, iterators, algorithms: all good stuff. And it's not really a trick, per se, but for me the best thing about the STL is functors. Iterators might be the glue that hold the STL car together, but functors are the engine that makes it really save you time and write better code. Which is, after all, what the STL is all about.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜