# 查验机器环境
| #include <iostream> |
| |
| using namespace std; |
| |
| int main() { |
| cout << "Standard Clib: " << __STDC_HOSTED__ << endl; |
| cout << "Standard C: " << __STDC__ << endl; |
| |
| cout << "ISO/IEC " << __STDC_ISO_10646__ << endl; |
| return 0; |
| } |
| |
| Standard Clib: 1 |
| Standard C: 1 |
| ISO/IEC 201706 |
# 返回函数的名字
| |
| |
| #include <iostream> |
| #include <string> |
| |
| using namespace std; |
| |
| const char *hello() { return __func__; } |
| const char *world() { return __func__; } |
| |
| struct TestStruct { |
| TestStruct() : name(__func__) {} |
| const char *name; |
| }; |
| |
| int main() { |
| cout << hello() << ", " << world() << endl; |
| TestStruct ts; |
| cout << ts.name << endl; |
| return 0; |
| } |
| |
| hello, world |
| TestStruct |
# 变长参数宏定义
| |
| |
| #include <stdio.h> |
| |
| #define LOG(...) { \ |
| fprintf(stderr, "%s: Line %d:\t", __FILE__, __LINE__); \ |
| fprintf(stderr, __VA_ARGS__); \ |
| fprintf(stderr, "\n"); \ |
| } |
| |
| int main() { |
| int x = 3; |
| LOG("x = %d", x); |
| return 0; |
| } |
| |
| |
| va_args.cpp: Line 13: x = 3 |
# 静态断言与 static_assert
- 断言宏 assert 只用于程序运行时
- #error 只在编译器预处理时有效
- static_assert 用于程序编译时进行断言
static_assert 接收两个参数,一个 bool 值,一个字符串警告信息。
static_assert 的断言表达式的结果必须时在编译时期就可以计算的表达式,及必须是常量表达式。
| #include <cstring> |
| |
| using namespace std; |
| |
| template <typename T, typename U> int bit_copy(T &a, U &b) { |
| static_assert(sizeof(b) == sizeof(a), "the parameters of bit_copy must have same width."); |
| memcpy(&a, &b, sizeof(b)); |
| } |
| |
| int main() { |
| int a = 0x2468; |
| double b; |
| bit_copy(a, b); |
| return 0; |
| } |
# noexcept 修饰符与 noexcept 操作符
- noexcept 不会抛出异常,通过调用 std::terminate () 来终止程序的运行,则这样可以减少异常机制带来的开销(比如,不用进行栈帧的一级一级的展开),有效的阻止了异常的传播与扩散。
- 但也可能存在一些问题,比如 noexcepet 后无法保证对象的析构函数的正常调用,无法保证栈的自动释放等等。
- C++11 默认将 delete 函数设置为 noexcept,即 nocept (true),可以提高程序的安全性。
| `void operator delete(void *) noexcept; |
| void operator delete[](void *) noexcept; |
| void *operator new(std::size_t) noexcept(false); |
| void *operator new[](std::size_t) noexcept(false); |
| |
| void except_func() noexcept; |
| void except_func() noexcept(常量表达式) |
| |
| template <class T> |
| void fun() noexcept(noexcept(T(()))) {} |
# 快速初始化成员变量
| #include <string> |
| |
| using namespace std; |
| |
| struct C { |
| C(int i) : c(i) {}; |
| int c; |
| }; |
| |
| struct Init { |
| int a = 1; |
| string b("hello"); |
| C c(1); |
| }; |
| |
| int main() { |
| Init temp; |
| return 0; |
| }` |
# override 和 final
- override:保证在派生类中声明的重载函数,与基类的虚函数有相同的签名(函数名,参数,const 属性);
- final:阻止类的进一步派生 和 虚函数的进一步重写。
加了 override,明确表示派生类的这个虚函数是要重写基类的,如果派生类与基类虚函数的签名不一致,编译器就会报错。一个虚函数被声明为 final,则派生类不能再重写它。
# 模板函数的默认模板参数
c98 不支持函数模板的默认模板参数,c11 支持。
| void Deparm(int m = 3) {} |
| template <typename T = int > |
| class DefClass {}; |
| template <typename T = int > |
| void DefTempParm() {} |
对于类模板,如果定义模板类的默认模板参数,必须按照从左到右定义。而对于函数模板没有此要求。
| template<typename T1, typename T2 = int> class DefClass1; |
| template<typename T1 = int, typename T2> class DefClass2; |
| |
| template<typename T, int i = 0> class DefClass1; |
| template<int i= 0, typename T> class DefClass1; |
| |
| template<typename T1 = int, typename T2> void DefFunc1(T1 a, T2 b); |
| template<int i= 0, typename T> void DefFunc2(T a); |