trivial,non-trivial 函数,POD类型
enable_if
unsigned char
static_cast && dynamic_cast
trivial,non-trivial 函数,POD类型
- trivil,即不重要的,在以下四类函数中区分。
- 构造函数 ctor
- 拷贝构造函数 copy
- 拷贝赋值运算符(赋值函数) assignment
- 析构函数 dtor
这四种函数只要被显示声明(定义的话当然更是了),则为non-trivial类型。
class A { A(); }; //声明
class B { B(){} }; //定义
class C { };
int main() {
//构造函数是否为trivial类型
cout << is_trivially_constructible<A>::value << endl;//0
cout << is_trivially_constructible<B>::value << endl;//0
cout << is_trivially_constructible<C>::value << endl;//1
}
- Plain old data structure,即POD,为C++定义的一类数据结构,其经过二进制拷贝后数据仍保持不变的类型。POD类型包括标量类型,POD类类型,cv-限定类型,还有以其为基类的数组类型。
- 标量类型(Scalar type):相对于复合类型,标量类型只能有一个值。C++语言中,int,char,enum,double,loob等均可归类为标量类型。
- POD类类型:可以从两方面来归类该类型。(1) 构造函数,拷贝/移动构造函数,拷贝/移动赋值运算符,析构函数均为平凡的(non-trivial)且不包含虚函数,虚基类的类型即为POD类型。 (2) POD类类型是不具有以下成员的类型:指针到成员类型的非静态数据成员,非POD类类型的非静态数据成员,应用类型的非静态数据成员,用户定义的拷贝,赋值,析构操作。
class A { A(); }; //声明
class B { B(){} }; //定义
class C { };
class D { ~D(); }; //声明析构函数
int i= 1;
class E { static int i; }; //声明静态变量
int main() {
//类类型是否为trivial类型
cout << is_trivial<A>::value << endl;//0
cout << is_trivial<B>::value << endl;//0
cout << is_trivial<C>::value << endl;//1
//类类型是否为POD
cout << is_pod<A>::value << endl; //0
cout << is_pod<B>::value << endl; //0
cout << is_pod<C>::value << endl; //1
//我们可以看到这俩函数其实差不多
cout << "--------------------" << endl;
cout << is_pod<D>::value << endl; //0
cout << is_pod<E>::value << endl; //1
//其他就不测了......
}
参见
- https://www.cnblogs.com/zzyoucan/p/3918614.html
- https://baike.baidu.com/item/pod/13976181?fr=aladdin
enable_if
最近摸鱼又摸到这么宝贝。
template <class Other1 = Ty1, class Other2 = Ty2,
typename = typename std::enable_if<
std::is_default_constructible<Other1>::value &&
std::is_default_constructible<Other2>::value, void>::type>
constexpr pair()
: first(), second(){}
先不谈这个typename = 到底是在搞哪样。就这个enable_if,我还没搞懂到底有什么用,先设个坑吧。给出的链接讲的很详细,就是例子里的东西看不懂。
参见
- https://www.jianshu.com/p/a961c35910d2
unsigned char
-
char 与unsigned char均为一个字节,唯一的区别就是char类型最高位为符号位,表示范围为[-128,127];unsigned char表示范围[0,255]。
-
int/unsigned int变量赋值给 unsigned char变量是会发生字节截断(9位和高于9位的将被程序自动丢弃)。
unsigned int a = 0xFFFFFFF7;
unsigned char b = (unsigned char)a;
printf("%x", b);//f7
- 在表示byte时,都用unsigned char。通常情况下,byte没有符号位,而将byte赋值给unsigned char之外的任何类型,都有可能发生符号扩展现象(包括unsigned char)。
参见 - https://baike.baidu.com/item/unsigned%20char/3426526?fr=aladdin
static_cast &&dynamic_cast
static_cast其实就是c语言的强制类型转换…
char a = 'c';
int b = static_cast<char>(a);
cout << b << endl;//99
double*c = new double;
void *d = static_cast<void*>(c);
cout << typeid(d).name() << endl;//void*
int e = 10;
const int f = static_cast<const int>(e);
const int g = 10;
//错误,static_cast不能丢掉表达式的cv属性
int *h = static_cast<int*>(&g);
//正确,这条其实可以隐式转换。
int i = static_cast<int>(g);
dynamic_cast将基类对象指针或引用转换到继承类指针,static_cast同样可以执行此操作。需要注意的是static_cast,没有运行时检查来保证转换的安全性,dynamic_cast具有类型检查功能,这在基类向派生类转换时需要尤其容易出错。
参见
- https://blog.csdn.net/u014624623/article/details/79837849
最后我们来看一个例子。
template<class Size>
char *fill_n(char *first, Size n, const char&value) {
memset(first, static_cast<unsigned char>(value), n);
return first + n;
}
<algorithm>中的fill函数的一个重载,用value填充first指向的内存,n是填充的字节数。
…其他也没什么好解释的了。