debug & release
Add -ggdb to the command line when debugging and -O2 -DNDEBUG for release builds. Use the former for now.
warning levels
Add the following flags to your command line: -Wall -Weffc++ -Wextra -Wconversion -Wsign-conversion
warning2error
Add the following flag to your command line: -Werror
compile vs interpret
compilation - Difference between compiled and interpreted languages? - Stack Overflow
常量表达式由编译期常量和可编译期计算的函数组成,不属于常量表达式的就是运行时表达式
编译期常量有
- Literals (e.g. ‘5’, ‘1.2’)
- Constexpr variables (we discuss these shortly in lesson 5.5 — Constexpr variables)
- Const integral variables with a constant expression initializer (e.g.
const int x { 5 };). This is a historical exception — in modern C++, constexpr variables are preferred. - Non-type template parameters (see 11.10 — Non-type template parameters).
- Enumerators (see 13.2 — Unscoped enumerations).
不属于编译期常量的常量是运行期常量
通过const声明编译期常量的两个缺点
- 不能直观判断是哪种常量
- 不支持非整型 因此需要使用constexpr,它要求用常量表达式来初始化(否则引发编译错误),保证是编译期常量 对于std::string和std::vector声明constexpr,需要对应改为支持constexpr的std::stringview和std::array 对于普通的函数,不能声明constexpr参数,const参数被视作运行时常量
In modern C++, the term inline has evolved to mean “multiple definitions are allowed”. Thus, an inline function is one that is allowed to be defined in multiple translation units (without violating the ODR).
但是编译器要求必须在每个使用该声明的单元给出实现且实现必须相同
建议在头文件实现inline函数
inline variables
A constant expression (which may contain constexpr function calls) is only required to evaluate at compile-time in contexts where a constant expression is required.
Always test your constexpr functions in a context that requires a constant expression, as the constexpr function may work when evaluated at runtime but fail when evaluated at compile-time.
constexpr函数的参数不是constexpr的,constexpr函数暗示inline,而constexpr变量并不默认暗示inline
Rule
The compiler must be able to see the full definition of a constexpr (or consteval) function, not just a forward declaration.
Best practice
Constexpr/consteval functions used in a single source file (.cpp) can be defined in the source file above where they are used.
Constexpr/consteval functions used in multiple source files should be defined in a header file so they can be included into each source file.
转换stringview到string,有一定开销
static_cast
对于const string&,只有传入string时开销较小,传入stringview和字符串字面量时都有一定开销
而stringview开销始终不大
Prefer passing strings using std::string_view (by value) instead of const std::string&, unless your function calls other functions that require C-style strings or std::string parameters.
使用viewer的条件,viewer期间不修改或者销毁观察对象(未定义行为,或者可以理解为观察对象的修改和销毁会使得相关view无效),view不能修改观察对象
小心不要用string字面量(""s)来初始化stringview,因为stringview只是viewer,不能保持这个临时对象的存活
可以安全返回stringview的两种情况
1.使用c字符串,生存周期为整个程序
2.来自stringview参数(又有需要注意的是,谨慎使用临时对象构造stringview
There is one important subtlety here. If the argument is a temporary object (that will be destroyed at the end of the full expression containing the function call), the std::string_view return value must be used in the same expression. After that point, the temporary is destroyed and the std::string_view is left dangling.)
stringview视图自身可以修改
z = (a, b); // evaluate (a, b) first to get result of b, then assign that value to variable z.
z = a, b; // evaluates as "(z = a), b", so z gets assigned the value of a, and b is evaluated and discarded.internal linkage
可见性为编译单元内,同名标识符独立,不违反ODR
static int g_x{}; // non-constant globals have external linkage by default, but can be given internal linkage via the static keyword
// same for functions
const int g_y{ 1 }; // const globals have internal linkage by default
constexpr int g_z{ 2 }; // constexpr globals have internal linkage by defaultinline变量是external linkage
scope,duration和lifetime,linkage
duration和lifetime有点难区分
static
全局变量,static函数/类变量
automatic
块作用域
dynamic
thread
线程创建到退出
生命周期
开始when the storage with proper alignment and size is allocated and the object is initialized
结束when it’s detroyed, or the dtor is called, or its storage is released or reused by non-nested object
placement new+手动析构函数
用相同类型placement new后,原来的name,指针和引用仍然有效
注意const对象
trivial dtor
a class has a trivial dtor if
- dtor implicitly declared(就是没写?) or =default
- non-virtual dtor and 所有非静态成员有trivial dtor
通过lifetime,可以做指针相关优化strict aliasing
scope针对标识符,指的是可见和可用
duration针对变量,指的是创建和销毁时间
linkage决定同名标识符是否指向相同的对象 linkage 是控制链接时候符号可见性的
local变量是no linkage的,意味着和其他同名的标识符独立
如static local变量具有static duration和block scope
Static local variables that are zero initialized or have a constexpr initializer can be initialized at program start.
Static local variables that have no initializer or a non-constexpr initializer are zero-initialized at program start. Static local variables with a non-constexpr initializer are reinitialized the first time the variable definition is encountered.之后不再初始化
anything declared inside an inline namespace is considered part of the parent namespace. However, unlike unnamed namespaces, inline namespaces don’t affect linkage.
std::exit()
std::exit is called implicitly when main() returns.
使得一个程序正常退出,可以设置非0状态码
std::exit不会清理任何local变量,如果程序行为依赖local变量析构会导致问题(如文件句柄泄漏)
atexit可以注册清理函数
模版是odr的特例,模版生成的函数是implictly inline的,所以也不违反odr
模版参数推断不会进行类型转换,只有解析函数重载时会进行
- Lvalue expressions are those that evaluate to variables or other identifiable objects that persist beyond the end of the expression.
- Rvalue expressions are those that evaluate to literals or values returned by functions/operators that are discarded at the end of the expression. 左值又可分为是否可修改的,影响是否能左值引用 When a const lvalue reference is directly bound to a temporary object, the lifetime of the temporary object is extended to match the lifetime of the reference.