Boost库学习

Boost库学习

Boost库是一套开放源代码、高度可移植的C++库。

Boost库主要包括一下几个大类:字符串及文本处理、容器、迭代子、算法、函数对象和高阶编程、泛型编程、模板元编程、并发编程、数学相关、纠错和测试、数据结构、输入/输出、跨语言支持、内存相关、语法分析、杂项。

字符串处理

1)应用:字符串——数值(boost/lexical_cast.hpp)

C语言解决方法是使用atoi,atod,atol,atold等

#include <iostream>
#include <boost/lexical_cast.hpp>
int main()
{
    using boost::lexical_cast;
    int a = boost::lexical_cast<int>("123456");
    std::cout << a << std::endl;
    double b = boost::lexical_cast<double>("123.12");
    std::cout << b << std::endl;
    long double c = lexical_cast<long double>("123.11");
    std::cout << c << std::endl;
    return 0;
}

2)应用:数值——字符串(boost/lexical_cast.hpp)

C语言解决方法是sprintf函数:

char s[100];
sprintf(s, "%f", 123.12);

// boost库实现
#include <iostream>
#include <boost/lexical_cast.hpp>
int main()
{
    using std::string;
    const double d = 123.12;
    string s = boost::lexical_cast<string>(d);
    std::cout << s << std::endl;
    return 0;
}

3)异常处理

#include <iostream>
#include <boost/lexical_cast.hpp>
int main()
{
    using std::cout;
    using std::endl;
    int i;
    try{
        i = boost::lexical_cast<int>("abc");
    }
    catch(boost::bad_lexical_cast & e)
    {
        cout << e.what() << endl;
        return 1;
    }
    cout << i << endl;
    return 0;
}

4)实现原理:lexical_cast依赖于字符流std::stringstream(会自动引入头文件stringstream,相当于把源类型读入字符流中,再写到目标类型中,就可以了。

int d = boost::lexical_cast<int>("123");
// 其核心实现
int d;
std::stringstream s;
s << "123";
s >> d;

boost中的lexical_cast不仅仅局限于字符串类型与数值类型之间的转换:可以在任意可输出到stringstream的类型和任意可从stringstream输入的类型间转换。

内存管理

内存管理一直是令C++程序最头疼的工作,C++继承了C那高效而又灵活的指针,使用起来稍微不小心,就会导致内存泄露、野指针、访问越界等问题。C++程序员项目Java、C#等语言的垃圾回收机制。虽然C++提供了智能指针std::auto_ptr,但问解决问题。

解决上面问题使用的是智能指针。智能指针代理了原始“裸”指针的行为,又添加了更多更有用的特性。智能指针能够做到在退出作用域时——不管事正常流程离开,还是因为异常离开——总调用delete来析构对上动态分配的对象。

int main()
{
    auto_ptr<class_need_resource> p1(new class_need_resource);
    auto_ptr<demo_class> p2(factory.create());
} //离开作用域,p1,p2自动析构从而释放内存等资源

auto_ptr构造函数接受new操作符或者对象工厂创建出的对象指针作为参数,从而代理了原生指针。虽然它是一个对象,但因重载了operator *和operator->,其行为非常类似指针,可以把它用在大多数普通指针可用的地方。当退出作用域是,C++语言会保证auto_ptr对象销毁,调用auto_ptr的析构函数,进而使用delete操作符删除原始指针释放资源。auto_ptr是标准C++库提供的。

boost库提供了六种智能指针,包括scoped_ptr、scoped_array、shared_ptr、shared_array、weak_ptr和intrusive_ptr,从各个方面增强std::auto_ptr,且异常安全。

智能指针

智能指针是存储指向动态分配(堆)对象指针的类。除了能够在适当的时间自动删除指向的对象外,他们的工作机制很像C++的内置指针。智能指针在面对异常的时候格外有用,因为他们能够确保正确的销毁动态分配的对象。他们也可以用于跟踪被多用户共享的动态分配对象。此外,智能只能还能处理线程安全,提供写时复制,确保协议,并提供远程交互服务。智能指针大部分使用是用于生存期控制,阶段控制。他们使用operator->和operator *来生成原始指针,这样智能指针看上去就像一个普通指针。

scoped_ptr:用于处理单个对象的唯一所有权,与std::auto_ptr不同的是,scoped_ptr可以被复制。
scoped_array:与scope_ptr类似,用于处理数组。
shared_ptr:允许共享对象所有权。
shared_array:允许共享数组所有权。

线程编程

多线程编程是当今互联网应用服务程序普遍使用的方法,用于提高与多客户链接时的效率,为达到最大吞吐量,事物服务器在单独的线程上运行服务程序,GUI应用程序将那些费时,复杂的处理以线程的形式单独运行,以此来保证用户界面能够及时响应用户的操作。

boost库提供线程编程,且安全。

1)创建线程

boost::thread类代表一个可执行线程。缺省构造函数创建一个代表当前执行线程的实例。重载的构造函数以一个不需任何参数的函数对象作为参数,并且没有返回值。这个构造函数创建一个新的可执行线程,它调用那个函数对象。Boost线程库使用函数对象代替函数指针,函数对象本身可以携带线程所需数据。此方法灵活,类型安全。当和Boost.Bind这样的功能库一起使用时,此方法可以让你传递任意数量的数据给新建的线程。线程对象可以使用==和!=判断是否为同一个线程,还可用join等待线程执行完毕。

2)互斥体

不同线程同时访问共享区域时,需要使用互斥体。当一个线程要改写共享区域中某个数据,而此时另一个线程正在读这个数据,那结果未知。为避免这种情况方法,就需要使用一些特殊的原始类型和操作。其中最基本的就是互斥体。互斥体一次只允许一个线程访问共享区。当一个线程想要访问共享区时,首先要锁住互斥体。如果其他线程已经锁住互斥体,就必须等到那个线程将互斥体解锁,来保证同一时刻只有一个线程能访问共享区域。

Boost线程支持两种互斥体:简单互斥体和递归互斥体。如果同一个线程对互斥体上了两次锁,就会发生死锁,即让所有等待解锁的线程一直等待下去。有了递归互斥体,单个线程可以对互斥体多次上锁,当然也必须解锁同样次数来保证其他线程可对这个互斥体上锁。

线程可用以下三种方法对一个互斥体加锁:

1)一直等到没有其他线程对互斥体加锁;

2)如果有其他互斥体已经对互斥体加锁,就立即返回;

3)一直等到没有其他线程互斥体加锁,直到超时。

4)mutex类通过typedef定义在RAII中实现的类型来实现互斥体的上锁和解锁。

3)条件变量

有时候仅仅靠锁住共享资源来使用它是不够的。有时候共享资源只有某些状态的时候才能够使用。如某个线程如果要从堆栈中读取数据,如果栈中没有数据就必须等待数据被压栈,此情况的同步使用互斥体是不够的。需要利用另一种同步方式——条件变量。

条件变量的使用总是和互斥体及共享资源联系在一起。线程首先锁住互斥体,然后检验共享资源的状态是否处于可使用状态。如果不是,那么线程就等待条件变量。要指向这样的操作,就必须在等待的时候将互斥体解锁,以便其他线程可以访问共享资源并改变其状态。它还得保证从等到的线程返回时互斥体是被上锁的。当另一个线程改变了共享资源的状态,它就要通知正在等待条件变量的线程,并将之返回等待的线程。

4)线程局部存储

大多数函数都是不可重入的。即某个线程已经被调用了一个函数时,如果你在调用同一个函数,则是不安全的。一个不可重入的函数通过连续的调用来保存静态遍历或者是返回一个指向静态数据的指针。如std::strtok就是不可重入的,因为它使用静态变量来保存要被分割成符号的字符串。

两种方法可让不可重用的函数变成可重用的函数。第一种:改变接口,用指针或引用替代原先使用静态数据的地方。第二种:不用改变共有接口,而是用本地存储线程来代替静态数据。

Boost线程提供了智能指针boost::thread_specific_ptr来访问本地存储线程。每一个线程第一次使用这个智能指针的实例时,初始值为NULL,必须先检查这个它的指针是否为空,并未它赋值。Boost线程库保证本地存储线程中保存的数据会在线程结束后被清除。

5)仅运行一次的实例

如何使初始化工作安全?方法是一次实现。一次实线在一个应用程序只能执行一次。如果多个线程同时执行这个操作,那么真正执行的只有一个,其他线程必须等这个操作作数。使用一个指针和一个表示这个routine是否已经被调用的特殊标志。Boost库使用boost::call_once来支持一次实现,并定义一个标志boost::once_flag及一个初始化这个标志的宏BOOST_ONCE_INIT。

参考指南:http://stlchina.huhoo.net/bin/view.pl/Main/BoostChina

你可能感兴趣的:(boost)