本篇是看完《深入理解C++11:C++11新特性解析与应用》后做的笔记的上半部分. 这本书可以看作是《C++Primer》的进阶版, 主要是更加详细地介绍了C++11的一些常用设计和标准库设施, 很多知识点都在面试中会遇到, 值得一读.
阅读并笔记的途中我跳过了一些之前已经总结过的内容, 而对于一些自己看书后依然没搞清楚的内容(例如SFINAE和内存模型)搜索资料进行了扩展, 还补充了一些原书没有介绍但稍微有所相关的内容, 参考文献在每一段的开头给出. 全文6.6k字, 慢慢来吧.
才疏学浅, 错漏在所难免, 后续若有所修改会同步存于我的Github仓库, 点击底部"阅读原文"可跳转(Study-Notes/Content/《深入理解C++11》笔记/上 at main · ZFhuang/Study-Notes (github.com))
预定义宏 https://docs.microsoft.com/zh-cn/cpp/preprocessor/predefined-macros?view=msvc-170
__func__
所在处的函数名称, 可以用在初始化成员列表中__DATE__
编译日期__FILE__
当前文件的名称__LINE__
所在处的行号__TIME__
编译时间_Pragma()
和#pragma
一样, 用来指示编译器进行一些行为, 不过前者属于操作符因此可以用在宏中调用__VA__ARGS__
变长宏参数, 用于替换掉宏函数中省略号代表的字符串__cplusplus
返回cpp版本, C语言则无定义, 用于混合编译<cassert>
中提供assert()
宏, 用于运行时断言; static_assert()
用于编译期断言, 接受表达式和提示信息两个参数static_assert()
是静态的, 能在任何命名空间中使用, 因此最好写在外部作为提示并防止用到局部变量noexcept
和 noexcept()
指明某函数不能抛出异常(若抛出则直接terminate), 参数可以用bool值来决定是否允许抛出, ture就不允许. 此举是为了节省抛出异常的额外开销. C++11的delete操作和析构函数默认是noexcept的char
和宽字符串wchar_t
连接的时候会统一位宽字符串然后连接long long
至少64位的长整型, 字面值以LL结尾sizeof()
可以对类成员表达式使用了friend T;
)final
可以阻止后续派生类的覆盖, 函数声明的尾部加上override
可以强制派生类进行覆盖.o
中, 如果一个模板文件被多个文件实例化就会产生多份重复代码, 没有extern的话此时重复的模板会冲突. 有了extern后编译器会自动删除重复的实例化模板, 不但节省内存还节省了多余的实例化时间using Base::Func;
来获取基类被隐藏的同名成员函数(包括构造函数, 此时被称为继承构造函数)的访问, 从而在外部可以自动调用基类构造using Base::Base;
)暴露出来, 自身的默认构造函数就和之前的隐藏规则一样, 不会被自动生成std::move()
能强制使一个左值变为右值, 但是不会改变其生命周期std::forward()
来完美转发(或者直接用std::move()
)std::move_if_noexcept
的版本, 其在当前函数没有noexcept时主动转换为左值应用从而调用拷贝构造版本. 但显然这种做法损失性能std::forward()
的核心原理explict
可以防止参数发生隐式类型转换, 用于构造函数和operator中initializer_list
, 可以用作函数的一种重载参数ReturnType operator "" X(Args)
作为后缀操作符, 其允许我们将字符串字面值加上自定义的后缀X来转换为目标字面类型\0
结尾is_trivial<T>::value
来判断一个类是否Plain, 用is_standard_layout<T>::value
判断一个类是否Old. 最终可以用is_pod<T>::value
直接判断是否PODSFINAE: Substitution Failure is not an Error | Top-Up C++ [C++ #02] https://www.youtube.com/watch?v=mNxAqLVIaW0 C++模板进阶指南:SFINAE https://zhuanlan.zhihu.com/p/21314708 Substitution Failure is not an Error https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
// From: https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
// 这段是在展现SFINEA下模板函数的匹配逻辑
struct Test {
typedef int foo;
};
template <typename T>
void f(typename T::foo) {} // f1 针对类的特化
template <typename T>
void f(T) {} // f2 更加泛化的一种模板类型
int main() {
// 调用f1和f2皆可, 参数列中f1版本参数有定义foo, Test更符合f1的参数, 因此实例化f1
f<Test>(10);
// 只能调用f2, 因为在这个匹配过程中若把int替换到f1的参数列中, int没有定义foo, 失败
// 由于SFINEA的原因int对f1的尝试不算做实例化的error, 而属于匹配过程中的一次failure
f<int>(10);
}
std::enable_if
, 那么要想到这是和SFINEA相关的模板编程特性. 下面是这类做法的一个简单样例// From: https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
// 这段在展示如何利用模板在编译器判断模板参数是否具有某个定义的符号
template <typename... Ts>
using void_t = void;
// 继承true_type和false_type是为了能用value返回结果
// f1, 无法满足T::foobar的参数列要求, 因此候选项只剩下这个泛化的版本
template <typename T, typename = void>
struct has_typedef_foobar : std::false_type {};
// f2, 进行了T::foobar这种典型的无意义偏特化, 仅用于筛选掉不匹配的参数
template <typename T>
struct has_typedef_foobar<T, void_t<typename T::foobar>> : std::true_type {};
struct foo {
// typedef也行
using foobar = float;
};
int main() {
std::cout << std::boolalpha;
// int匹配的时侯无法满足f2特化的参数列中的T::foobar要求, 因此无法实例化f2
// 比较之下, int可以满足f1的要求, 因此实例化f1, 从而继承了false_type
std::cout << has_typedef_foobar<int>::value << std::endl; // 输出 false
// foo两者都可以满足, 同时对于f2来说匹配更加特化, 因此实例化了f2, 从而true
// 通过这样对于函数匹配的hack操作, 我们可以在编译期获得某个模板参数是否具有某个属性
std::cout << has_typedef_foobar<foo>::value << std::endl; // 输出 true
}
concept
以更好的语法取代auto
是静态类型推导, 必须被初始化auto t = 1, &r = t, *p = &r;
是合法的begin
和end
函数, 且支持++
和==
, 常与auto共用, 但要注意range-for中的auto是解引用后的对象而不是迭代器type_id(a).name()
返回类的名称. C++11给typeinfo新加入了hash_code()这个函数可以返回类型唯一的哈希值decltype
也是编译期的类型推导, 但是其从一个表达式作为参数返回该表达式的类型std::result_of()
内部的type命名本质就是decltypeenum
代表对应到整数值的一些名字(常量数值的别名), 从0开始, 且其成员在所在的范围内全局可见enum class TypeName : type { Name0, Name1 };
直接获得了强作用域, 转换限制, 可指定底层类型三大优点::
), 因此匿名枚举类没有什么意义, 除非用decltype重新指名扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有