ifndef
ifndef的用法在于避免重复包含和编译,在同一头文件被多次引用且又同时编译时,容易出现声明冲突,两者通常同时使用:
#ifndef xxxx
#define xxxx
xxxx
…
xxxx
#endif
第一行ifndef会首先判断是否已经定义,如果已经定义将直接跳到#endif,否则将执行#define命令。
uint32_t
uint32_t是C/C++标准中定义的类型。包含以下三个头文件中任意一个,就可以保证使用uint32_t类型:<inttypes.h>、<stdint.h>、<cstdint> 而uint32是某些编译器定义的别名,以方便使用。类似:
typedef uint32_t uint32
uint32_t比uint32的可移植性更好
!!
!!不是C ++中的单个令牌,只需解析两次应用!运算符即可。
由于a是指针而不是类类型的对象,因此!不能重载。如果a是空指针,则定义为返回true,否则返回false。
!的第二个应用程序简单地否定了第一个!的结果。
表达式!!a等效于a != 0。
宏定义相关代码
const char* LogLevel::ToString(LogLevel::Level level) {
switch(level) {
#define XX(name) \
case LogLevel::name: \
return #name; \
break;
XX(DEBUG);
XX(INFO);
XX(WARN);
XX(ERROR);
XX(FATAL);
#undef XX
default:
return "UNKNOW";
}
return "UNKNOW";
}
上面这段代码就是用XX(name) 来代替
case LogLevel::name: \
return #name; \
break;
将name传到case语句中。其中#name 是将name变成字符串的意思。#undef 表示取消宏定义,XX宏定义只有在这一段才有用。
std::function(还是不太了解)
#include <functional>
std::function<int(int)> Functional;
表示可以通过Functional来条用一个参数为int型的函数。
std::get<n>()
std::vector<std::tuple<std::string, std::string, int> > vec;
for(auto& i : vec) {
if(std::get<2>(i) == 0) {
....
可以看到vec是一个tuple类型的vector,使用std::get<2>(i)能获取vector中的一个tuple的第二个元素。
智能指针reset
若p为智能指针对象(如:shared_ptr< int> p) 成员函数reset使用:
p.reset(q)
会令智能指针p中存放指针q,即p指向q的空间,而且会释放原来的空间。(默认是delete)
typeid
typeid 运算符用来获取一个表达式的类型信息。类型信息对于编程语言非常重要,它描述了数据的各种属性:
- 对于基本类型(int、float 等C++内置类型)的数据,类型信息所包含的内容比较简单,主要是指数据的类型。
- 对于类类型的数据(也就是对象),类型信息是指对象所属的类、所包含的成员、所在的继承关系等。
类型信息是创建数据的模板,数据占用多大内存、能进行什么样的操作、该如何操作等,这些都由它的类型信息决定。
typeid 的操作对象既可以是表达式,也可以是数据类型,下面是它的两种使用方法:
- typeid( dataType )
- typeid( expression )
dataType 是数据类型,expression 是表达式,这和 sizeof 运算符非常类似,只不过 sizeof 有时候可以省略括号( ),而 typeid 必须带上括号。
string::find_first_not_of()
正向查找在原字符串中第一个与指定字符串(或字符)中的任一字符都不匹配的字符,返回它的位置。若查找失败,则返回npos。(npos定义为保证大于任何有效下标的值。)
|