条款44:容器的成员函数优先于同名的算法
这个条款应该是毫无疑问的,下面是书中给出的理由:
1)成员函数往往更快;
2)成员函数通常与容器集合的更加紧密,特别是关联容器,而这时算法所不能的,算法比较处理通用性的东西;
void listTest() {
// 成员函数
list<int> l1{1,9,7,6,4};
list<int> l2{2,8,3,5,};
l1.sort();
l2.sort();
// l1.merge(l2);
// 算法
list<int> l;
std::merge(l1.begin(), l1.end(), l2.cbegin(), l2.cend(), std::back_inserter(l));
return;
}
条款45:正确区分count, find, binary_search, lower_bound, upper_bound, equal_range
场景一、区间无序
场景二、区间有序
场景三、关联容器
直接上一张书中的截图
练习代码
void vectorTest() {
vector<int> vec{5, 5, 9, 7, 8, 6, 1, 2, 6, 7, 6, 3, 4};
// 无序场景的查找、计数
auto i1 = std::find(vec.cbegin(), vec.cend(), 6); // 使用 operator==
if (i1 != vec.cend()) {
// exist 6
} else {
// not exist 6
}
int num = std::count(vec.cbegin(), vec.cend(), 6); // 6的数量
auto i2 = std::find_if(vec.cbegin(), vec.cend(), [](int x) { return x == 6; }); // 是否存在6
// 有序场景的查找、计数
std::sort(vec.begin(), vec.end());
bool exist6 = std::binary_search(vec.cbegin(), vec.cend(), 6); // 是否存在6
auto il = std::lower_bound(vec.cbegin(), vec.cend(), 6);
if (il != vec.end() && *il == 6) {
// exist 6
// 特别说明,这儿的用法在别的地方可能有问题,*il == 6是相等性的判断,其实算法是等价性的判断
// 因此如果序列中是对象,排序规则中很可能只用到了部分成员,比如工号,而没有用到员工名字,则这样的相等判断是有问题的
// upper_bound同理
}
auto iu = std::upper_bound(vec.cbegin(), vec.cend(), 6);
int num6 = std::distance(il, iu); // 6的数量
auto ipair = std::equal_range(vec.cbegin(), vec.cend(), 6);
if (ipair.first != ipair.second) {
// exist 6
}
num6 = std::distance(ipair.first, ipair.second); // 6的数量
num6 = ipair.second - ipair.first; // 6的数量
// 有序场景针对某些位置的操作
vec.insert(vec.begin(), 0); // 仅测试,这个插入会导致顺序错误
vec.insert(std::lower_bound(vec.cbegin(), vec.cend(), 6), 20); // 仅测试,这个插入会导致顺序错误
std::sort(vec.begin(), vec.end());
vec.insert(std::upper_bound(vec.cbegin(), vec.cend(), 6), 20); // 仅测试,这个插入会导致顺序错误
std::sort(vec.begin(), vec.end());
vec.erase(vec.begin(), std::lower_bound(vec.cbegin(), vec.cend(), 5)); // 将5前面的元素都删除
vec.erase(std::upper_bound(vec.cbegin(), vec.cend(), 6), vec.end()); // 将6后面的元素都删除
return;
}