C++ boost 簡單應用

簡介

C++的著名擴充函式庫
功能(節錄):

  • regex
  • function binding
  • lambda functions
  • unit tests
  • smart pointers
  • noncopyable, optional
  • serialization
  • generic dates
  • portable filesystem
  • circular buffers
  • config utils
  • generic image library
  • program options
  • threads

所有功能

安裝:sudo apt-get install libboost-all-dev

基本功能

簡化語法

foreach

1
2
3
4
5
6
7
8
#include <boost/foreach.hpp>
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello ){ // equals to for (auto c : hello) in c03
std::cout << ch << endl;
}

//convient way to use
#define foreach BOOST_FOREACH

實作方法

lexical_cast

可以轉換成其他格式

1
2
3
4
5
#include <boost/lexical_cast.hpp>
...
double j = 233.211321231;
string mystring = boost::lexical_cast<string>(j);
double k = boost::lexical_cast<double>(mystring);//k = 233.211

split

1
2
3
4
5
#include <boost/algorithm/string.hpp>
...
string stringtobesplit = "AA/BB-CC";
vector<string> tokens;
boost::split(tokens, stringtobesplit, boost::is_any_of("/\-"));

Smart Pointers

Basic properties of smart pointers

  • no ownership at all
    • smart pointer cannot delete the object, because it doesn’t own it
  • transfer of ownership
    • only one smart pointer can ever point to the same object at the same time
    • If the smart pointer is to be returned from functions, the ownership is transferred to the returned smart pointer
    • Transfer of ownership cannot really be implemented in C++ currently, because object will be copied after return
      • only can use the copy constructor to implement that transfer of ownership
  • share of ownership
    • multiple smart pointers can point to the same object at the same time
    • can be implemented by having a copy constructor

Categorizing smart pointers

  • scoped_ptr
    • neither transferable nor sharable (= normal pointer)
    • when it goes out of scope, it is destroyed
  • shared_ptr
    • shares ownership
    • reference counted so it can see when the last copy of it goes out of scope and then it frees the object automatically
    • 所有使用同一筆資料的指標都不再使用後自動釋放
  • weak_ptr
    • non-owning smart pointer
    • reference a managed object (managed by a shared_ptr) so it will not add a reference count
      • If you need to access the object, you can lock the management of it (to avoid that in another thread a shared_ptr frees it while you use the object)
    • If weak_ptr points to an object already deleted, it will notice you by throwing an exception
    • It is most beneficial when you have a cyclic reference: Reference counting cannot easily cope with such a situation
  • intrusive_ptr
    • like a shared_ptr
      • does not keep the reference count in a shared_ptr
      • but call helper functions to increse/decrese the count
        • helper function need to be defined by the object that is managed
        • reference count is not anymore internal to the smart pointer, but the smart pointer uses an existing reference counting mechanism
    • typically used when there is a 3rd party smart ptr you must use
  • unique_ptr
    • transfer of ownership pointer
    • cannot copy it, but can move it by using C++1x’s move constructors
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
std::vector< scoped_ptr<T> > tPtrVec;
{
scoped_ptr<T> tPtr(new T());
tPtrVec.push_back(tPtr);
// raw T* is freed
}
tPtrVec[0]->DoSomething(); // accessing freed memory
//--------------------------------------
std::vector< shared_ptr<T> > tPtrVec;
{
shared_ptr<T> tPtr(new T());
// This copy to tPtrVec.push_back and ultimately to the vector storage
// causes the reference count to go from 1->2
tPtrVec.push_back(tPtr);
// num references to T goes from 2->1 on the destruction of tPtr
}
tPtrVec[0]->DoSomething(); // raw T* still exists, so this is safe
//--------------------------------------
std::vector< weak_ptr<T> > tPtrVec;
{
shared_ptr<T> tPtr(new T());
tPtrVec.push_back(tPtr);
// num references to T goes from 1->0
}
shared_ptr<T> tPtrAccessed = tPtrVec[0].lock();
if (tPtrAccessed[0].get() == 0){
cout << "Raw T* was freed, can't access it"
}
else{
tPtrVec[0]->DoSomething(); // raw
}
//--------------------------------------
unique_ptr<type> p(new type);
unique_ptr<type> q(p); // not legal!
unique_ptr<type> r(move(p)); // legal. p is now empty and r owns the object
unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!

Chinese Explaination

1
2
3
4
5
6
7
8
9
10
11
#include <boost/shared_ptr.hpp>
void safeclose(FILE*fp) {
if(fp) {
fclose(fp);
}
}
void some_fn() {
boost::shared_ptr<FILE> fp( fopen(myfilename, "a+t"), safeclose );
//body of the function, and when ever it exits the file gets closed
fprintf( fp.get(), "a message\n" );
}

Reference

Advantage of using boost libraries
Most used parts of boost