美文网首页算法与C++
c++ STL 重剑无锋

c++ STL 重剑无锋

作者: Vophan | 来源:发表于2019-02-01 22:02 被阅读11次

在现在,总是有人鼓吹c++是一门不好的语言,说他比c慢,说他发展变了味道,说他语法歧义,但是没有一个人可以说他不强大。

这里引用轮子哥在知乎的一个回答:

STL作为一个模范放在那里人们都不看,
非要去写披着C++外衣的C语言
披着C++外衣的java
中枪踩坑学不会都是正常的。这根本不是C和C++哪个好的问题,是大众对C++的误解造成的。在用C++的时候,自己水平不高,就不要去用C的部分。都是因为人类的意志力太脆弱,才造成这么多问题的。


之前,我感觉不到c++ 强大在哪里?今天我接触到c++的STL的通用容器与通用算法后,我感觉c++ 不在是那个c with class。

通用算法

注:下面内容为我从Thinking In Cpp学习到的东西以及自己写的代码

copy

为什么对这个函数这么有感觉?是因为一直以来,我都觉得c/c++的数组赋值方式令人不舒服,不可以按值传递,简直了。
所以当看到这个函数时,眼前一亮。

示例:

//
// Created by vophan on 19-2-1.
//

#include <algorithm>
#include <cassert>
#include <cstddef>

int main() {
    int a[] = {1,2,3,4,5};
    const size_t SIZE = sizeof a / sizeof a[0];
    int b[SIZE];
    std::copy(a, a+SIZE, b);
    for (size_t i = 0; i < SIZE; ++i) {
        assert(a[i] == b[i]);
    }
}

然后,在这里注意一下,最后的for循环,我们如果不想看到他呢?

//
// Created by vophan on 19-2-1.
//

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <iostream>

int main() {
    int a[] = {1,2,3,4,5};
    const size_t SIZE = sizeof a / sizeof a[0];
    int b[SIZE];
    std::copy(a, a+SIZE, std::ostream_iterator<int>(std::cout, "\n"));
//    std::copy(a, a+SIZE, b);
//    for (size_t i = 0; i < SIZE; ++i) {
//        assert(a[i] == b[i]);
//    }
}

什么是ostream_iterator?
先卖个关子。

equal

我们前面检验数组是否复制成功,用了断言和循环,现在我们换一个方式:

//
// Created by vophan on 19-2-1.
//

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <iostream>

int main() {
    int a[] = {1,2,3,4,5};
    const size_t SIZE = sizeof a / sizeof a[0];
    int b[SIZE];
    std::copy(a, a+SIZE, b);
    assert(std::equal(a, a+SIZE, b));
}

当然,如果equal只能比较两个整数数组,那确实没什么意思,但是实际上他可以处理任何一种类型。但是你需要重载==运算符。

struct student {
    float grade;
    std::string name;
    float height;
    student(float grade, std::string name, float height) {
        this->grade = grade;
        this->name = name;
        this->height = height;
    }
    bool operator==(student &s) const;
};

bool student::operator==(student &s) const {
    if (grade == s.grade and height == s.height and name == s.name) {
        return true;
    } else {
        return false;
    }
}

但是要注意:

如果要把一个序列(sequence)拷贝到一个容器(container)中去,通常用std::copy算法,代码如下:
std::copy(start, end, std::back_inserter(container));

back_inserter

这个东西是什么呢?对比两段代码大家就知道了。

#include <cassert>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstddef>

using namespace std;

int main() {
    int a[] = {1,2,3,4,5};
    const size_t SIZE = sizeof a / sizeof a[0];
    vector<int> v1(a, a + SIZE);
    vector<int> v2(SIZE);
    copy(v1.begin(), v1.end(), v2.begin());
    assert(equal(v1.begin(), v1.end(), v2.begin()));
}
#include <cassert>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstddef>

using namespace std;

int main() {
    int a[] = {1,2,3,4,5};
    const size_t SIZE = sizeof a / sizeof a[0];
    vector<int> v1(a, a + SIZE);
//    vector<int> v2(SIZE);
    vector<int> v2;
    copy(v1.begin(), v1.end(), back_inserter(v2));
    assert(equal(v1.begin(), v1.end(), v2.begin()));
}

没错,back_inserter为我们省去了初始化vector的过程,实际上,back_inserter是将原来的“为后面的元素赋值”变为了“将元素插入到后面”。

replace_copy_if && remove_copy_if && replace_if

我理解这几个函数其实就是:选择型复制,复制符合某种条件的值,尽管这在python里算是基操,但是在c++里用模板编程实现还是蛮麻烦的,而且我认为:这应该也是c++中回调机制的体现,将调用者与制造者分离,互不干涉。

#include <algorithm>
#include <iostream>
#include <cstddef>

using namespace std;

bool gt15 (int x) {return x > 15;}

int main() {
    int a[] = {10, 20, 30};
    const size_t size = sizeof a / sizeof a[0];
    int b[size];
    int *endb = remove_copy_if(a, a+size, b, gt15);
    int *begb = b;
    while (begb != endb) {
        cout<<*begb++<<endl;
    }
    return 0;
}

注意:执行结果是10,说明是remove了符合条件的值,所以很符合这个名字

#include <algorithm>
#include <iostream>
#include <cstddef>

using namespace std;

bool containE(string s) {return s.find("e") != string::npos;}

int main() {
    string a[] = {
            "read",
            "my",
            "lips"
    };
    const size_t size = sizeof a / sizeof a[0];
    string b[size];
    string *endb = replace_copy_if(a, a+size, b, containE, "kiss");
    string *begb = b;
    while (begb != endb) {
        cout<<*begb++<<endl;
    }
}

同理,自行理解replace
而replace_if 则是改变自己的序列,而不是复制。

c++

相关文章

  • c++ STL 重剑无锋

    在现在,总是有人鼓吹c++是一门不好的语言,说他比c慢,说他发展变了味道,说他语法歧义,但是没有一个人可以说他不强...

  • 重剑无锋

    一份完整的投资报告,由前言、投资逻辑、行业分析、护城河、风险分析、当前市场形势判断、标的组合及预期目标等要...

  • 重剑无锋

    多谢你 高歌伴我白螺杯 在这 将暮的时节 多谢你 打马而过 赠我一场疑似风月 在这 梵唱的长街 钟磬噙着寒烟 月色...

  • 重剑无锋

    "重剑无锋"出自金庸小说《神雕侠侣》中,杨过在石壁上所见到独狐求败的刻字:"......剑魔独狐求败的第三...

  • 重剑无锋

    感谢两天旅途,让我终于把这颗光芒海采撷入怀。 下午在候车室漫长等待的过程中,读书的心思被负情绪全面压制,谁想上车打...

  • 重剑无锋

    今天听刘润老师”得到十日谈“,受益匪浅,记录课程内容如下: 商业的本质是“交易”。疫情当头,交易暂停,经济承压,也...

  • 重剑无锋

    最近申请加入一个社群,社群要求学员每天用100分钟做70道法考题目。 对我来说是个很大的挑战,但是很想用这种方法逼...

  • 重剑无锋

    想法只是一瞬间的思考,容易忘记,不易留存。而当用文字记下来的时候,想法就成了心得,心得可以慢慢积累。当用心得指导行...

  • 重剑无锋

    迪士尼CEO的10条领导力原则,看是平淡无奇,实则重剑无锋! 1.乐观。一位优秀的领导人最为重要的特质之一就是乐观...

  • 重剑无锋

    金庸先生笔下的江湖一直都被人津津乐道,他天马行空的想象力,为世人塑造了一个十分美妙的世界,在他的小说中不仅有奇遇神...

网友评论

    本文标题:c++ STL 重剑无锋

    本文链接:https://www.haomeiwen.com/subject/ciirsqtx.html