标签: C++Primer 学习记录 泛型算法
==
运算符、sort算法需要使用<
运算符。泛型算法本身不会执行容器的操作,它们只会运行与迭代器之上,执行迭代器的操作。即,一个算法永远不会直接改变底层容器的大小。accumulate(vec.cbegin(), vec.cend(), 0);
这里面有三个编程假定: string sum = accumulate(vec.cbegin(), vec.cend(), "")
就是错误的,因为 const char*并没有+
运算符。[捕获列表](参数列表) ->返回类型 {函数体}
。
auto f = [] { return 42; };
。如果忽略返回类型, lambda根据函数体中的代码推断出返回类型。
size_t v1 = 42; auto f = [v1] {return v1;}; v1 = 0; auto j = f(); // J为 42;v1在 lambda创建时被 // 拷贝,随后对外面的 v1的修改与 lambda中的 v1无关
size_t v1 = 42; auto f = [&v1] {return v1;}; v1 = 0; auto j = f(); // J为 0;lambda中的 v1只是外面 v1的引用
size_t v1 = 42; // f能够改变它所捕获的局部变量 auto f = [v1] () mutable {return v1;}; v1 = 0; auto j = f(); // J为 43
bind
函数,它可以看作是一个函数适配器。
_n
是占位符,表示新调用对象的参数。这些名字都定义在名为 placeholders的命名空间中,使用之前需要声明。using std::placeholders::_1; // check6是一个可调用对象,接受一个 string类型的参数 // 并用此 string和值6来调用 check_size auto check6 = bind(check_size, _1, 6);
auto g = bind(f, a, b, _2, c, _1);
// g(x, y)会调用 f(a, b, y, c, x)
// 按单词长度由短至长排序
sort(w.begin(), w.end(), isShorter);
// 按单词长度由长至短排序
sort(w.begin(), w.end(), bind(isShorter, _2, _1));
void f(int& n1, int& n2, const int& n3) {
++n1;
++n2;
}
int n1 = 1, n2 = 2, n3 = 3;
auto bf_1 = bind(f, n1, ref(n2), cref(n3));
n1 = 10;
n2 = 11;
n3 = 12;
bf_1(); // 此时,n1 == 1, n2 == 12, n3 == 12。这是因为 n1是值拷贝,
// 函数之外的 n1并没变化。而 n2是引用,值会发生变化。
// 下面的语句是错误的,cref中保存的是 const引用,f中相应的参数是普通引用!
auto bf_2 = bind(f, n1, cref(n2), cref(n3));
>>
来读取流,因此 istream_iterator要读取的类型必须定义了输入运算符。此外,默认初始化迭代器,可以作为尾后值的迭代器,来表明流数据的结束。istream_iterator<int> in_iter(cin), eof; // 从 cin读取 int vector<int> vec(in_iter, eof); // 从迭代器范围构造 vec
<<
输出运算符。可以提供第二个参数,表示在输出每个元素后都会打印的字符串。另外,结合 copy算法一起使用,比编写循环更为简单。不允许空的或表示尾后位置的 ostream_iterator。ostream_iterator<int> out_iter(cout, " "); for (auto e : vec) *out_iter++ = e; // 该赋值语句实际上将元素写到 cout cout << endl;
++
,也需要支持--
,因此不能从 forward_list或一个流迭代器创建反向迭代器。base
成员函数将其转换回普通迭代器。// 在一个逗号分隔的列表中查找最后一个元素并将其输出 auto rcomma = find(line.crbegin(), line.crend(), ','); // 错误,将逆序输出单词的字符 cout << string(line.crbegin(), rcomma) << endl; // 正确,从逗号的下一个位置开始读取字符直到末尾 cout << string(rcomma.base(), line.cend()) << endl;
反向迭代器与普通迭代器间的关系
[line.crbegin(), rcomma)
和[rcomma.base(), line.cend())
必须指向 line中相同的元素范围。因此,从一个普通迭代器初始化一个反向迭代器,或是给一个反向迭代器赋值时,结果迭代器与原始迭代器指向的并不是相同的元素。make_move_iterator
函数将一个普通迭代器转换为一个移动迭代器。某些算法会根据迭代器解引用后得到的是左值或右值引用来调用元素类型的拷贝构造或移动构造函数。
unique(beg, end); // 使用 == 运算符比较元素 unique(beg, end, comp); // 使用 comp 运算符比较元素
_if
后缀。find(beg, end, val); // 查找输入范围中 val第一次出现的位置 find(beg, end, pred); // 使用 comp 运算符比较元素
reverse(beg, end); // 反转输入范围中元素的顺序 reverse_copy(beg, end, dest); // 将元素按逆序拷贝到 dest