Contents
Updated on 2021-05-08
- Lecture: Scott Meyers - Effective Modern C++
- Distinguish lvalues and rvalues
- Understand type deduction
- Understand std::move and std::forward
- Prefer auto to explicit types when declaring objects
- Remember that auto + {expr} => std::initializer_list
- Distinguish universal references from rvalue references
- Pass and return rvalue references via std::move, universal references via std::forward
- Understand reference collapsing
- Assume that move operations are not present, not cheap, and not used
- Avoid default capture modes
- Make const member functions thread-safe
- Book: Effective Modern C++ Chapter 1
Distinguish lvalues and rvalues
Lvalues
- General rule: If you can take its address, it’s an lvalue
- Conceptual motivation: Lvalues may not be moved from
Rvalues
- Conceptually: temporary objects. e.g., by-value function return
- Conceptual motivation: Rvalues may be moved from
Understand type deduction
Template type deduction
General problem:
|
|
- Given type of expr, what are the type of T and ParamType?
- Three general cases:
- ParamType is a reference or pointer
- ParamType is a universal reference
- ParamType is neither reference nor pointer (By-Value Parameters)
T和
auto
的推導規則一樣
class template don’t have class deduction, only function template have deduction.
ParamType is a reference or pointer
- If expr’s type is a reference, ignore that (T的&會被去掉)
- Pattern-match expr’s type against ParamType to determine T
ParamType is a universal reference
- 如果expr是Lvalue,T和param都會是Lvalue reference
- 如果expr是Rvalue,T會是原本的type,param是Rvalue reference
在C++ 14可以使用
auto&&
來當作lambda function的parameter
By-Value Parameters
- 如果expr是pointer以外的type,可視為copy,去掉
&
、const
、volatile
- 如果expr是pointer type,T和ParamType的type跟expr一樣
Array Arguments & Function Arguments
- In C/C++, type of array and pointer is same as a function parameter.
void f(int param[]);
is same asvoid f(int *param);
- In C/C++, function types can decay into function pointer
- expr在Pointer、Function pointer,推導出來的param不一樣
expr | T | param |
---|---|---|
int* | T | int* |
int(*)() | T | int(*)() |
int* | T* | int* |
int(*)() | T* | int(*)() |
int* | T& | int*& |
int(*)() | T& | int(&)() |
int* | T&& | int*& |
int(*)() | T&& | int(&)() |
|
|
- 神奇的範例
|
|
Q: 甚麼時候parameter可以不需要name?
auto Type Deduction
- Same as template type deduction, except with braced initializers
- auto deduces
std::initializer_list
but template don’t
- auto deduces
braced initializer don’t have a type, 只有auto有特殊規則
|
|
auto
in a function return type or a lambda parameter implies template type deduction, notauto
type deduction
|
|
decltype Type Deduction
- decltype(name) ≡ declared type of name
|
|
- dectype(Lvalue expr of type T) ≡ T&
- Names are lvalues, but decltype(name) rule beat decltype(expr) rule:
|
|
operator[]
回傳的type要根據container而定
|
|
Function return type
- 把
auto
放在function return type,參考access1()、 access2() - 加上
decltype
規則,decltype(auto)
跟回傳值的type一樣,參考access3() - 讓parameter
c
能夠接受Rvalue和Lvalue,c
要使用Universal reference type。如果c
是Rvalue,會在function結束後消失,回傳值會發生問題,所以return時要用forward
,參考access4()、access5()
|
|
decltype(auto)
的規則也可以來宣告變數
|
|
- 小心return a reference of local variable,因為decltype(Lvalue expr of type T) ≡ T&
|
|
How to view deduced types
- IDE,
std::type_info::name
可能會有問題,Compiler Diagnostics和boost::typeindex
是比較可靠的,重點是自己要弄懂…
Compiler Diagnostics
|
|
Runtime Output
std::type_info::name
|
|
boost::typeindex
|
|
Комментарии