1.compressed_pair
#include<boost/compressed_pair.hpp>
作用:使用模板元编程技术和多重继承来优化空类成员,可以“压缩”pair大小来节约空间。
使用如下,分析:
(1)空类是指没有非静态成员变量(会增加类实例大小),没有虚函数(会导致虚表指针)。
(2)仿照make_pair()实现make_compressed_pair()。
(3)输出4是空类被优化掉了,输出8是空类因字节对齐等于4,输出1是其中一个空类被优化掉了。
#include<iostream>
#include<boost/compressed_pair.hpp>
using namespace std;
class emptyClass
{
public:
void show() { cout << "empty class" << endl;; }
};
template<typename T1, typename T2>
boost::compressed_pair<T1, T2>
make_compressed_pair(T1 t1, T2 t2)
{
return boost::compressed_pair<T1, T2>(t1, t2);
}
int main()
{
auto pair1=make_compressed_pair(42, emptyClass());
pair1.second().show(); //输出empty class
cout << sizeof(boost::compressed_pair<int,emptyClass>) << endl; //输出4
cout << sizeof(pair<int, emptyClass>) << endl; //输出8
cout << sizeof(boost::compressed_pair<emptyClass, emptyClass>) << endl; //输出1
cout << sizeof(pair<emptyClass, emptyClass >) << endl; //输出2
return 0;
}
2. checked_delete/checked_array_delete
#include<boost/checked_delete.hpp>
作用:可以在编译器保证delete/delete[]删除的是一个指向”完整类型“的指针,避免运行期发生未定义行为,是更加智能的delete/delete[]。
使用1如下,分析:删除函数前只有类声明,所以调用do_delete()时,没有调用析构函数,将导致资源未释放等未定义行为,可能会警告【删除指向不完整“demo”类型的指针;没有调用析构函数】;而使用checked_delete()既方便又避免了这种写法错误。
使用2如下,分析:
(1)只声明而没有具体定义,使用delete p时,可能会警告;而使用checked_delete()时,代码无法编译,会报错【static_assert failed: 'Type must be complete' 】和【使用了未定义类型“demo” 】。
(2)【注意】checked_delete()删除指针后并不会将其设置为nullptr。
使用建议:因某些原因不能使用智能指针,必须手工管理内存,那就使用checked_delete/check_array_delete,它可以保证在编译期就发现隐藏错误。
3.addressof
#include<boost/utility/addressof.hpp>或#include<memory>
作用:若重载了operator&的类,直接使用&会失效(实际上调用了重载的operator&)但addressof()总能获得操作对象的真实地址。
使用如下,分析:使用&p获得的是p.y地址,main函数结束时,会因为下溢而中断【Run-Time Check Failure #2 - Stack around the variable 'p' was corrupted] 。
使用建议:怀疑某个类可能重载了operator&,那就使用addressof获取对象真正地址。
4.base_from_member
#include<boost/utility/base_from_member.hpp>
作用:有时基类需要由派生类的成员变量来初始化,但基类必须在派生类之前完成初始化,而那时的派生类的成员是未定义的。解决:1、把派生类的成员移动到另一个辅助基类中。2、base_from_member 使用多重继承和模板技术提供了用成员初始化基类的惯用法。base_from_member 默认有11个构造函数,最大支持10个参数;也可以定义宏#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 2 (3个构造函数,最大支持2个参数)。
使用如下,分析:base没有被正确初始化。
解决1,把派生类的成员移动到另一个辅助基类中。
#include<iostream>
#include<complex>
#include<boost/utility/base_from_member.hpp>
using namespace std;
class base
{
public:
base(complex<int>c) { cout << "base:" << c << endl; }
};
class pbase //手工编写的辅助类
{
protected:
complex<int>c; //成员变量都移动到这个辅助类
pbase(int a,int b):c(a,b){}
};
class derived :private pbase,public base
{
public:
derived(int a, int b) :pbase(a, b), base(c) { cout << "derived:" << c << endl; }
};
int main()
{
derived d(1, 2);
return 0;
}
解决2,使用base_from_member。【注意】成员变量的名字是member。
#include<iostream>
#include<complex>
#include<boost/utility/base_from_member.hpp>
using namespace std;
class base
{
public:
base(complex<int>c) { cout << "base:" << c << endl; }
};
class derived :private boost::base_from_member<complex<int>>,public base
{
using pbase = boost::base_from_member<complex<int>>; //简化
public:
derived(int a, int b) :pbase(a, b), base(member) { cout << "derived:" << member << endl; }
};
int main()
{
derived d(1, 2);
return 0;
}
5.conversion
隐式类型转换由编译器自动完成:char,short->int->unsigned->long->double, float->double。
显式类型转换由程序员手工强制完成:
(1)使用()。
(2)标准转型操作符,能够避免许多任意转型引起的潜在错误。
const_cast:用于增加或删除const、volatile修饰。
static_cast:可以显式执行隐式类型转换。
reinterpret_cast:对目标的内存二进制位进行低层次的重新解释。
dynamic_cast:用于多态对象(即存在虚函数的对象)间类型转换,将基类指针或引用转换为派生类指针或引用,从而访问派生类特有的成员。【注意】引用转型失败会抛异常”bad_cast“;指针转型失败会返回一个空指针(nullptr),如果漏写检查代码(assert/if语句)会导致安全隐患,使用boost::polymorphic_downcast/boost::polymorphic_cast会更安全地进行多态对象间转型。
(3)boost::lexical_cast,用于基本数据类型和字符串之间的转换,使用如下。
#include<boost/lexical_cast.hpp>
【注意】boost::trim,用于去除字符串首尾的空白字符(空格、制表符、换行符等)。
#include<boost/algorithm/string.hpp>
#include<iostream>
#include<boost/lexical_cast.hpp>
#include<boost/algorithm/string.hpp>
using namespace std;
int main()
{
string str = " 12.3 ";
boost::trim(str);
double a = boost::lexical_cast<double>(str);
cout << a << endl;
return 0;
}
polymorphic_downcast:引用/指针转型。对指针安全操作:断言转型成功。
polymorphic_cast:指针转型。对指针安全操作:空指针检查,若空指针抛异常”bad_cast“。
#include<boost/polymorphic_cast.hpp>
#include<iostream>
#include<boost/polymorphic_cast.hpp>
using namespace std;
class base {
public:
virtual ~base() {}
};
class derived : public base {
public:
void derivedFunction() {
cout << "derived function" << endl;
}
};
int main()
{
base* b = new derived;
derived* d = boost::polymorphic_cast<derived*>(b);
d->derivedFunction();
derived& d2 = boost::polymorphic_downcast<derived&>(*b); //转引用只能用polymorphic_downcast
d2.derivedFunction();
delete b;
return 0;
}
6.numeric_cast
#include<boost/numeric/conversion/cast.hpp>
作用:在数字转型时进行范围检查,如果超出范围就抛异常"bad_cast",相比static_cast更安全,避免潜在错误。
使用如下:分析:使用static_cast不异常,使用numeric_cast超出范围,上溢异常。