My inspiration from reading *C++ Primer*, *Effective C++*, *More Effective C++*, *The C++ Standard Library* and some experience from coding.
Include:
* Debug
* C++ Syntax
* Habit && Optimization
* Trick
* Trap
* Reference
My inspiration from reading *C++ Primer*, *Effective C++*, *More Effective C++*, *The C++ Standard Library* and some experience from coding.
Include:
* Debug
* C++ Syntax
* Habit && Optimization
* Trick
* Trap
* Reference
here are some slides for introduction to C++. this slide is merely for basic understanding for C++. this powerpoint is written in Traditional Chinese(TW) and is owned by a group named "Awakening Lion" which I participate in.
Since the previous LTS, JDK 17, was released in 2021, there are quite lots of features added into the Java specification. In this year, the latest JDK 21 LTS version is released and brings us many formal functions to improve our daily works. This session will focus on the new features, including String Templates, Sequenced Collections, Record Patterns, Pattern Matching for switch, Unnamed features and Virtual Threads.
6. Loop: range-based
• for (int i = 0; i < v.size(); ++i) // bad
• cout << v[i] << 'n';
• for (auto p = v.begin(); p != v.end(); ++p) // bad
• cout << *p << 'n';
• Constructs that cannot overflow do not overflow (and usually run faster):
• for (auto& x : v) // range-based for,
• cout << x << 'n';
• for (int i = 1; i < v.size(); ++i) // 无法使用 range-for, 因为需要2个元素
• cout << v[i] + v[i - 1] << 'n';
• for (int i = 0; i < v.size(); ++i) // v.size可能改变, 所以range-based for可能无法使用
• cout << f(v, &v[i]) << 'n';
8. Strongly typed enum
• 不能与int互相转换 (类型安全)
– enum Color {R, G, B}; // before c++11
– enum class Color {R, G, B}; // strongly typed
– Color c = Color::R;
– if (0 == c) // Error: cannot convert
– if (0 == static_cast<int>(c)) // ok
9. Raw string literals
• 不用escape特殊字符
– string raw_pattern=R"((+|-)?[[:digit:]]+)";
– string s = R"(This is the first line
– And this is the second line)“; //多行
– string cmd(R”(ls –l /home”));
– UTF支持, UR(“...”)
10. 初始化
• 一些例子
– int array[] = { 1, 2, 3 };
– std::vector v = { 1, 2, 3};
– std::map m = { {1, 2}, {2, 3} };
– struct Point {int x; int y;}
– Point p = {1, 2}; // ok
– std::vector f() { return {1, 2, 3} ;} // ok
– void f(std::vector<int> v);
– f({1, 2, 3}) // ok
• 对于struct, 按照顺序初始化各成员
• 对于class, 如果有用户定义的constructor, 那么{}调用constructor, 没有的话参考
上条
• 另外, 增加了in class initialization
– // in header file .H
– class Fun {
– public:
– int x = 0; // ok
– static constexpr int arr [4] = { 1, 2, 3, 4}; // also ok, 静态的话需要加上constexpr
11. 初始化:delegating
• Delegating构造函数: 在一个构造函数里调用另一个
– 防止代码重复
• class Date {
• int d;
• Month m;
• int y;
• public:
• Date(int ii, Month mm, year yy)
• :i{ii}, m{mm} y{yy}
• { if (!valid(i, m, y)) throw Bad_date{}; }
• Date(int ii, Month mm)
• :Date{ii, mm, current_year()} {}
• // ...
• };
12. using, static_assert
• using基本和typedef一样, 除了在模板中略有区别
– typedef std::unordered_map<int, int> MyMap;
– using MyMap = std::unordered_map<int, int>;
– using CallBackFunc = void(*)(int);
• class Rec {
• // ... data and lots of nice constructors ...
• };
• class Oper : public Rec {
• using Rec::Rec; // 构造函数同基类一样, 所以不必要再写一遍, 保证没有其他需要初始化的成员
• // ... no data members ...
• };
• static_assert:编译期检查
– static_assert(sizeof(long) >= 8, "64-bit code generation required for this library.");
– constexpr int version = 5;
– static_assert(version > 1, “version wrong”);
– static_assert(std::is_base_of<MyBase, T>::value, "T must be derived from MyBase");
– static_assert(std::is_default_constructible<T>::value, “T does not have default constructor”);
13. constexpr
• constexpr: 表达式编译期求值 // not only const
– constexpr int size=10; // vs: const int size = 10;
– int A[size]; // not ok with const
– constexpr bool master = false;
– template <bool B> void switchToMaster();
– switchToMaster<master>(); // not ok with const;
– constexpr还可以用在function:
• constexpr int min(int x, int y) { return x < y ? x : y; }
• constexpr int m2 = min(-1, 2); // compile-time evaluation
• int m3 = min(-1, v); // run-time evaluation
• constexpr不保证在编译时期求值
• 不要将所有的函数声明为constexpr, 确定是否可以在编译时求值
• constexpr隐含inline
14. noexcept
• 如果函数不会抛出异常, 或者函数无法处理异常, 那么申
明为noexcept
– bool func(int size) noexcept { // no throw, and not expecting
exception inside the function
– vector<int> vec(size); // this may throw
– return true;
– }
– 如果noexcept的函数内throw了异常, 那么std::terminate()将被
调用
– 析构函数应当不抛出异常, 所以默认析构函数隐含noexcept,
如果类所有成员的析构函数是noexcept的
– 有助于编译器优化代码执行路径
– constexpr函数隐含noexcept
– swap/move函数应当同样不抛出异常
17. lambda
• [ capture-list ] ( params ) { body }
– 效果相当于一个functor
– 因为有时候, 一些std的函数需要提供一个functor来作为参数, 比如
std::for_each, 而你写一个functor的话也就这一个地方用到了,
lambda就是为了简化这种过程, 相当于in place一个functor
– 一些例子:
• std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ })
– []: capture list, lambda内如果需要用一些外面的变量的话
• [x]: capture by value
• [&x]: capture by reference
• [&]: capture any by reference
• [=]: capture any by value
• [this]: capture class members
• [=, &x]: by value, except for x (by reference)
– 返回值由编译器推定,也可以指定
• [](int)->bool { /* do something here*/ })
18. lambda
• 可以用作初始化变量
– 例如,比较复杂的,或者const变量
• const string var = [&]{
• if (!in) return ""; // default
• string s;
• for (char c : in >> c)
• s += toupper(c);
• return s;
• }();
19. move
• lvalue, rvalue, xvalue, glvalue
– lvalue: (这样叫的原因是它能出现在=的左边)
• With identy, cannot be moved from
– prvalue:
• Without identy, can be moved from
– xvalue:
• With identy, can be moved from
– glvaue:
• lvalue or xvalue
– rvalue:
• prvalue or xvalue
int prvalue();
int& lvalue();
int&& xvalue();
20. move
• std::move()
– 这个函数并不move任何东西
– 它实际上返回一个&& (rvalue reference)
– 避免对lvalue作std::move(), 会遗留下一个处于无效状态的对象,如果之后使用的话?
• void f() {
• string s1 = “sss";
• string s2 = s1; // copy
• assert(s1 == “sss");
• // bad, if you want to keep using s1's value
• string s3 = move(s1); // s1可能无效了
• // s1可能改变了
• assert(s1 == "supercalifragilisticexpialidocious");
• }
• template<class T>
• void swap(T& a, T& b) {
• T tmp = move(a); // could invalidate a
• a = move(b); // could invalidate b
• b = move(tmp); // could invalidate tmp
• }
• IoBuf createBuffer(); //return is rvalue
• IoBuf& mybuffer = createBuffer(); // now moved from return object (temporary), no copy!