什么';你最喜欢的STL技巧是什么? 我在C++中已经编程了相当长的一段时间,但是我不时地遇到一个使用STL的代码片段,它会占用我相当长的时间和更多的代码来完成。

什么';你最喜欢的STL技巧是什么? 我在C++中已经编程了相当长的一段时间,但是我不时地遇到一个使用STL的代码片段,它会占用我相当长的时间和更多的代码来完成。,c++,stl,C++,Stl,STL需要相当长的时间才能习惯,而且关于如何使用STL的真实示例资源并不多。请与我分享你最喜欢的STL功能 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");

STL需要相当长的时间才能习惯,而且关于如何使用STL的真实示例资源并不多。请与我分享你最喜欢的STL功能

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);
}
#包括
#包括
#包括
bool是_cr(char c){返回c='\r';}
int main(int,char*a[]
{
std::ifstream是(“/dev/stdin”);
std::流操作系统(“/dev/stdout”);
(is)中的istreambuf_迭代器,结束;
std::ostreambuf_迭代器输出(os);
如果(in、end、out、is\U cr),则删除副本;
}

使用erase-remove习惯用法在线性时间内从向量中删除某些元素:

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

(手动循环遍历向量并在每个元素的基础上进行擦除将是二次时间。)

容器、迭代器、算法:都是好东西。就其本身而言,这并不是一个真正的把戏,但对我来说,STL最好的地方是。迭代器可能是将STL汽车连接在一起的粘合剂,但函子是真正节省时间和编写更好代码的引擎。毕竟,这就是STL的全部内容。

使用向量作为缓冲区。而不是:

int size_needed = GetData(NULL, 0);
char * buffer = new char[size_needed];
GetData(buffer, size_needed);
...
delete [] buffer;
使用向量:

int size_needed = GetData(NULL, 0);
std::vector<char> buffer(size_needed);
GetData(&buffer[0], size_needed);
int size\u needed=GetData(NULL,0);
std::向量缓冲区(需要大小);
GetData(缓冲区[0],需要大小);

共享ptr内的共享ptr

我有时使用std::shared_ptr自定义析构函数来实现一个简单的池工厂方法。不知道这算不算“把戏”

类工厂
{
std::queue pool_;//可能是tbb::concurrent_bounded_queue。也可以包含为共享的_ptr,以允许对象比工厂寿命长。
公众:
std::shared_ptr create()
{
std::载体ptr;
if(pool.empty())
ptr=std::使_共享();
其他的
{
ptr=std::move(pool.front());
pool_uu.pop();
}
return std::shared_ptr(ptr.get(),[=](Type*){pool_u.push(ptr)};;//销毁后放回池中
}
}

<代码> > P>我记得我在《代码》> Cop.Lang.C++中偶然发现(10年前)我真正喜欢的一个。
int main(int argc, char* argv[])
{
  std::vector arguments(argv+1, argv+argc);
  // whatever
}
今天,我不再用这个了。既然你已经有了迭代器,为什么还要把这些东西放到一个向量中,然后用迭代器处理呢?现在,这与其说是STL是一个容器和算法的集合,不如说是它给我们带来的通过迭代器粘合序列和算法的想法:

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);
}
模板
int进程参数(它开始,它结束)
{
//不管我们需要对这些论点做什么。。。
}
int main(int argc,char*argv[])
{
返回进程参数(argv+1,argv+argc);
}

(是的,我经常编写小型控制台实用程序。)

我最喜欢的是使用STL进行函数式编码。例如,计算小于2的元素:

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

不是特别有用,但我喜欢通过调用
std::partial_sum
来假装
std::iota
(其中C++0x不可用):

    std::vector<int> v(5, 1); // 1, 1, 1, 1, 1
    partial_sum(v.begin(), v.end(), v.begin()); // 1, 2, 3, 4, 5
标准向量v(5,1);//1, 1, 1, 1, 1 部分和(v.begin(),v.end(),v.begin());//1, 2, 3, 4, 5
至于我在生产代码中实际使用的东西:测试两个文件是否相同:

    if(equal(std::istreambuf_iterator<char>(file1),
             std::istreambuf_iterator<char>(),
             std::istreambuf_iterator<char>(file2)))
    { // files are equal, do whatever
if(相等(std::istreambuf_迭代器(file1),
std::istreambuf_迭代器(),
std::istreambuf_迭代器(文件2)))
{//文件是相等的,请执行任何操作

总的来说,我认为
部分和
内积
应该得到比他们看到的更多的爱。有了足够聪明的函子,他们可以做大事。

我最喜欢的STL技巧是避免使用

  • 阴极射线管
  • 原始指针(C++0x)

STL代码与蛮力等价物的表现力令人惊讶。

你的问题是什么?需要CW吗?@Paul:问题在标题中。@rstevens:booooo!:)@Paul:@sbi:叹气-欺凌真的-当然最好提出一个像CW这样有趣的问题,而不是仅仅把它关闭,因为它不是一个“真正的问题”?一个函子的例子!好吧,或多或少…我会投票支持你提到的擦除-删除习惯用法,但我没有投票权!另一个可怕的把戏由lambdas修复。你可以减少
std::bind2nd(std::less(),2)
to
\u 1<2
with
boost::lambda
:)@Fred:当然。最初的问题是关于STL,而不是boost…:)你不能也这样做:
删除拷贝(in,end,out,'\r')
并避免定义
is\u cr()
?它更像是STL功能的演示,而不是最小的dos2unix。我也可以使用std::cout/cin,而不显示它如何使用常规文件。您可能是指
std::vector一些很酷的变量名(argv+1,argv+argc)
对吗?否则它是一个临时向量,在分号处消失。令人震惊的是,它绝对是最糟糕的。可怕的局部性,由兰博达斯很好地修复了。@Hans:当你说“局部性”时,你是指有几十个小函子散布在整个地方吗?是的,eggzactly(很难故意拼错,达到15个字符)。@Hans:我同意这是一个巨大的失败。我不是想让你相信你错了(因为老实说,我不认为你错了),但我想说的是,对你创建的函子保持聪明是有帮助的。我不想用12个专门构建的函子,而是想尝试构建一个由几个普通函子组成的库,我可以反复使用。这很有帮助。@Hans:这里有个庸俗的问题要问你。你说lambdas是一个很好的修复方法。但是当你开始时,lambdas是真实的只是在调用点实例化了未命名的函子。除了lambda的代码就在那里这一事实,与函子的代码相比,还有什么区别吗
    if(equal(std::istreambuf_iterator<char>(file1),
             std::istreambuf_iterator<char>(),
             std::istreambuf_iterator<char>(file2)))
    { // files are equal, do whatever