兼容性
预定义宏
__STDC_HOSTED__
- 如果编译器的目标系统环境中包含完整的C库,那么这个宏就定义为1,否则值为0.
__STDC__
- C编译器通常用这个宏的值来表示编译器的实现是否与C标准一致。
- C++11标准中这个宏是否定义以及定义成什么值由编译器决定。
__STDC_VERSION__
- C编译器通常用这个宏来表示所支持的C标准的版本,比如1999mmL。
- C++11标准中这个宏是否定义以及定义成什么值由编译器决定。
__STDC_ISO_10646__
- 这个宏通常定义为一个yyyymmL格式的整数常量,例如199712L,用来表示C++编译环境符合某个版本的ISO/IEC 10646标准。
__func__
- 返回所在函数的名字
_Pragma
#pragma
是一条预处理指令,向编译器传达语言标准之外的一些信息。- C++11中,
_Pragma
是一个0与#pragma
预处理指令功能相同的操作符。
__VA_ARGS__
- 这个预定义宏可以在宏定义的实现部分替换省略号所代表的字符串。
1 2 3 4 5 6 7 8 9 10 |
#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); // xxx.cpp: Line 12: x = 3 } |
__cplusplus
1 2 3 4 5 6 |
#ifdef __cplusplus extern "C" { #endif // some other code #ifdef __cplusplus } |
静态断言
- 在C++中,程序员也可以定义宏NDEBUG来禁用assert宏。
一旦定义了NDEBUG宏,assert宏将被展开为一条无意义的C语句(通常会被编译器优化掉)。 - assert宏只有在程序运行时才起作用,而static_assert是编译时期的断言。
noexcept
- 表示其修饰的函数不会抛出异常。
- 与
throw()
动态异常声明不同的是,C++11中如果noexcept修饰的函数抛出了异常,编译器可以选择直接调用std::terminate()
函数来终止程序的运行。
这比基于异常机制的throw()
效率高一些,因为异常机制会带来一些额外开销,比如函数抛出异常,会导致函数栈被依次的展开,并依帧调用在本帧中已构造的自动变量的析构函数等。
friend
- 在C++11中,声明一个类为另一个类的友元时,不再需要class关键字。
可以为类模板声明友元了。
final
- 可以在派生过程中任意阻止一个接口的可重载性。
override
- 派生类在声明虚函数时使用了override,那么改函数必须重载其基类中的同名函数,否则代码将无法通过编译。
外部模板
- 避免编译器实例化出重复的代码。
a.h
1 |
template <typename T> void fun(T) {} |
a.cpp
1 |
template void fun<int>(int); |
b.cpp
1 |
extern template void fun<int>(int); |
通用特性
继承构造函数
- 派生类使用基类的构造函数
1 2 3 4 5 6 7 8 9 |
class A { A(int i) { } }; class B : public A { B(int i) : A(i) { } }; |
- 继承构造函数
1 2 3 4 5 6 7 8 |
class A { A(int i) {} A(double d, int i) {} }; class B : public A { using A::A; }; |
委托构造函数
1 2 3 4 5 6 7 |
class Info { public: Info() : Info(1) {} Info(int i) : i_(i) {} private: int i_; }; |
左值右值
- 等号左边的是左值,右边的是右值。
- 可以取地址的、有名字的是左值,不能取地址、没名字的是右值。
右值引用
- 关于浅拷贝的问题,可以通过深拷贝解决。而拷贝构造函数中为指针成员分配新的内存再进行内容拷贝的做法在C++编程中几乎被视为不可违背的。
- 在C++11中,可以在临时对象构造对象时,不使用拷贝构造。那就是移动构造语义。
- 在C++11中,右值引用就是对一个右值进行引用的类型。
1 |
T&& a = ReturnRValue(); |
std::move
- 将一个左值强制转化为右值引用。
是否可移动
-
里面:
1. is_move_constructible
2. is_trivially_move_constructible
3. is_nothrow_move_constructible
引用折叠
- 一旦定义中出现了左值引用,引用折叠总是优先将其折叠为左值引用。
- 模板对类型的推导规则:
- 当转发函数的实参是X的一个左值引用时,模板参数被推导为X&类型。
- 当转发函数的实参是X的一个右值引用时,模板参数被推导为X&&类型。
std::forword
- 实现了参数在传递过程中保持其值属性的功能,即若是左值,则传递之后仍然是左值,若是右值,则传递之后仍然是右值。
std::move和std::forward
- std::move执行到右值的无条件转换。
- std::forward只有当它的参数绑定到一个右值的时候,它才转换它的参数到一个右值。
explicit
- 避免构造函数被隐式调用。
- 作用于类型转换操作符上,意味着只有在直接构造目标类型或显示转换的时候可以使用该类型。
POD类型
- 通常用于说明一个类型的属性,尤其是用户自定义类型的属性。
- POD是个普通的类型,而不像一些存在虚函数虚继承的类型比较特别。
- POD可以用最老的memcpy进行复制,memset进行初始化等等。
- C++11将POD划分为两个概念的合集。
内联命名空间
- 可以声明一个内联的命名空间,允许程序员在父命名空间定义或特化子命名空间的模板。
模板别名
1 |
using sint = int; |
一般化的SFINEA规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
struct Test { typedef int foo; }; template <typename T> void f(typename T::foo) {} template <typename T> void f(T) {} int main() { f<Test>(10); // 调用#1 f<int>(10); // 调用#2 } |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ C++_友元、联合体、内联、static、指针、深浅拷贝06/21
- ♥ STL_slist08/28
- ♥ 深度探索C++对象模型:对象、构造、数据、函数、执行09/10
- ♥ 51CTO:C++语言高级课程二08/08
- ♥ Boost 程序库完全开发指南:容器算法数学文件08/24
- ♥ Bkwin一12/01