Chromium是一个伟大的、庞大的开源工程,很多值得我们学习的地方。
前面写道:
《跟Google学写代码–Chromium/base–stl_util源码学习及应用》
《跟Google学写代码–Chromium/base–windows_version源码学习及应用》
《跟Google学写代码–Chromium/base–cpu源码学习及应用》
《跟Google学写代码–Chromium工程中用到的C++11特性》
std::vector data
vector中的data方法:
Returns pointer to the underlying array serving as element storage. The pointer is such that range [data(); data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable in that case).
使用:
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector (5);
int* p = myvector.data();
*p = 10;
++p;
*p = 20;
p[2] = 100;
std::cout << "myvector contains:";
for (unsigned i=0; i<myvector.size(); ++i)
std::cout << ' ' << myvector[i];
std::cout << '\n';
return 0;
}
Algorithms
使用了很多algorithm中C++11新增的算法:
bool all_of(Iter first, Iter last, Pred pred);
bool any_of(Iter first, Iter last, Pred pred);
bool none_of(Iter first, Iter last, Pred pred);
Iter find_if_not(Iter first, Iter last, Pred pred);
OutIter copy_if(InIter first, InIter last, OutIter result, Pred pred);
OutIter copy_n(InIter first, InIter::difference_type n, OutIter result);
OutIter move(InIter first, InIter last, OutIter result);
OutIter move_backward(InIter first, InIter last, OutIter result);
pair<OutIter1, OutIter2> partition_copy(InIter first, InIter last, OutIter1 out_true, OutIter2 out_false, Pred pred);
Iter partition_point(Iter first, Iter last, Pred pred);
RAIter partial_sort_copy(InIter first, InIter last, RAIter result_first, RAIter result_last);
RAIter partial_sort_copy(InIter first, InIter last, RAIter result_first, RAIter result_last, Compare comp);
bool is_sorted(Iter first, Iter last);
bool is_sorted(Iter first, Iter last, Compare comp);
Iter is_sorted_until(Iter first, Iter last);
Iter is_sorted_until(Iter first, Iter last, Compare comp);
bool is_heap(Iter first, Iter last);
bool is_heap(Iter first, Iter last, Compare comp);
Iter is_heap_until(Iter first, Iter last);
Iter is_heap_until(Iter first, Iter last, Compare comp);
T min(initializer_list<T> t);
T min(initializer_list<T> t, Compare comp);
T max(initializer_list<T> t);
T max(initializer_list<T> t, Compare comp);
pair<const T&, const T&> minmax(const T& a, const T& b);
pair<const T&, const T&> minmax(const T& a, const T& b, Compare comp);
pair<const T&, const T&> minmax(initializer_list<T> t);
pair<const T&, const T&> minmax(initializer_list<T> t, Compare comp);
pair<Iter, Iter> minmax_element(Iter first, Iter last);
pair<Iter, Iter> minmax_element(Iter first, Iter last, Compare comp);
void iota(Iter first, Iter last, T value); // For each element referred to by the iterator i in the range [first,last), assigns *i = value and increments value as if by ++value
std::begin(), std::end()
Returns an iterator to the end (i.e. the element after the last element) of the given container c or array array. These templates rely on C::end() having a reasonable implementation.
使用:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main()
{
std::vector<int> v = { 3, 1, 4 };
if (std::find(std::begin(v), std::end(v), 5) != std::end(v)) {
std::cout << "found a 5 in vector v!\n";
}
int a[] = { 5, 10, 15 };
if (std::find(std::begin(a), std::end(a), 5) != std::end(a)) {
std::cout << "found a 5 in array a!\n";
}
}
std::enable_if, std::conditional
enable_if 的主要作用就是当某个 condition 成立时,enable_if可以提供某种类型
#include <iostream>
#include <type_traits>
// 1. the return type (bool) is only valid if T is an integral type:
template <class T>
typename std::enable_if<std::is_integral<T>::value,bool>::type
is_odd (T i) {return bool(i%2);}
// 2. the second template argument is only valid if T is an integral type:
template < class T,
class = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_even (T i) {return !bool(i%2);}
int main() {
short int i = 1; // code does not compile if type of i is not integral
std::cout << std::boolalpha;
std::cout << "i is odd: " << is_odd(i) << std::endl;
std::cout << "i is even: " << is_even(i) << std::endl;
return 0;
}
template
typedef std::conditional<true,int,float>::type A; // int
typedef std::conditional<false,int,float>::type B; // float
typedef std::conditional<std::is_integral<A>::value,long,int>::type C; // long
typedef std::conditional<std::is_integral<B>::value,long,int>::type D; // int
std::vector::cbegin(), std::vector::cend()
在迭代器中加入了const。
std::declval<class>()
Converts any type T to a reference type, making it possible to use member functions in decltype expressions without the need to go through constructors
declval的强大之处在于它能获取任何类型的右值引用,而不管它是不是有默认构造函数:
#include <utility>
#include <iostream>
struct Default { int foo() const { return 1; } };
struct NonDefault
{
NonDefault(const NonDefault&) { }
int foo() const { return 1; }
};
int main()
{
decltype(Default().foo()) n1 = 1; // type of n1 is int
// decltype(NonDefault().foo()) n2 = n1; // error: no default constructor
decltype(std::declval<NonDefault>().foo()) n2 = n1; // type of n2 is int
std::cout << "n1 = " << n1 << '\n'
<< "n2 = " << n2 << '\n';
}
emplace(), emplace_back(), emplace_front(), emplace_hint()
之前也有博客写过关于push_back和emplace_back的区别,直接上一段代码吧,以vector为例子:
#include <vector>
#include <string>
#include <iostream>
struct President
{
std::string name;
std::string country;
int year;
President(std::string p_name, std::string p_country, int p_year)
: name(std::move(p_name)), country(std::move(p_country)), year(p_year)
{
std::cout << "I am being constructed.\n";
}
President(President&& other)
: name(std::move(other.name)), country(std::move(other.country)), year(other.year)
{
std::cout << "I am being moved.\n";
}
President& operator=(const President& other) = default;
};
int main()
{
std::vector<President> elections;
std::cout << "emplace_back:\n";
elections.emplace_back("Nelson Mandela", "South Africa", 1994);
std::vector<President> reElections;
std::cout << "\npush_back:\n";
reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));
std::cout << "\nContents:\n";
for (President const& president: elections) {
std::cout << president.name << " was elected president of "
<< president.country << " in " << president.year << ".\n";
}
for (President const& president: reElections) {
std::cout << president.name << " was re-elected president of "
<< president.country << " in " << president.year << ".\n";
}
}
输出结果:
emplace_back:
I am being constructed.
push_back:
I am being constructed.
I am being moved.
Contents:
Nelson Mandela was elected president of South Africa in 1994.
Franklin Delano Roosevelt was re-elected president of the USA in 1936.
std::initializer_list<T>
初始化列表:
#include <iostream>
#include <vector>
#include <initializer_list>
template <class T>
struct S {
std::vector<T> v;
S(std::initializer_list<T> l) : v(l) {
std::cout << "constructed with a " << l.size() << "-element list\n";
}
void append(std::initializer_list<T> l) {
v.insert(v.end(), l.begin(), l.end());
}
std::pair<const T*, std::size_t> c_arr() const {
return {&v[0], v.size()}; // copy list-initialization in return statement
// this is NOT a use of std::initializer_list
}
};
template <typename T>
void templated_fn(T) {}
int main()
{
S<int> s = {1, 2, 3, 4, 5}; // copy list-initialization
s.append({6, 7, 8}); // list-initialization in function call
std::cout << "The vector size is now " << s.c_arr().second << " ints:\n";
for (auto n : s.v)
std::cout << n << ' ';
std::cout << '\n';
std::cout << "Range-for over brace-init-list: \n";
for (int x : {-1, -2, -3}) // the rule for auto makes this ranged-for work
std::cout << x << ' ';
std::cout << '\n';
auto al = {10, 11, 12}; // special rule for auto
std::cout << "The list bound to auto has size() = " << al.size() << '\n';
// templated_fn({1, 2, 3}); // compiler error! "{1, 2, 3}" is not an expression,
// it has no type, and so T cannot be deduced
templated_fn<std::initializer_list<int>>({1, 2, 3}); // OK
templated_fn<std::vector<int>>({1, 2, 3}); // also OK
}
<cmath>中的C++11新特性
string var=R"(raw_string)";
字面量,就像Python中的原始字符串。
tuple
元组,曾经令多少C++程序员羡慕的东西。
#include <iostream>
#include <tuple>
using namespace std;
int main() {
tuple<int, string, double> firstRecord(42, "myFirstName", 1.303);
tuple<int, string, double> secondRecord(21, "mySecondName", 2.638);
auto concat = tuple_cat(firstRecord, secondRecord);
/* for printing a tuple of any size you have to recursively use templates */
cout << get<1>(concat) << " " << get<4>(concat) << endl;
const int a = 1;
const int b = 2;
const double x = 2.34;
const double y = 4.27;
/* tie creates a tuple from lvalue references */
if(tie(a, x) < tie(b, y))
cout << "second arguments are larger" << endl;
/*
* use this to easily implement e.g.
* bool operator<(const A& rhs) const { return tie(n, s, d) < tie(rhs.n, rhs.s, rhs.d); }
*/
int f = 1;
int g = 2;
int h = 3;
/* unpack variables */
tie(f, g, h) = tie(g, f, h);
cout << "f " << f << ", g " << g << ", h " << h << endl;
/*
* f=2, g=2, h=3, because it is evaluated as follows:
* f = g; -> f=2
* g = f; -> g=2
* h = h; -> h=3
*/
}
std::unique_ptr<type>
智能指针