在现在,总是有人鼓吹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 则是改变自己的序列,而不是复制。
网友评论