scopted_ptr: 一旦獲取用戶的管理權,就無法取回.
template<class T>
class scopted_ptr{
private:
T * px;
scopted_ptr (scopted_ptr const &);
scopted_ptr & operator = (scopted_ptr const& ); //禁止復制,保證了scopted_ptr 的所有權.
public:
explicit scopted_ptr(T* p =0);//p必須是new的對象.
~scopted_ptr();
void reset(T*p =0);
T& operator*() const;
T * operator->()const;
T * get() const;//小心使用,這將scopted_ptr脫離,不能對這個指針做deleted操作,否則scopted_ptr析構時會再次刪除,程序會崩潰.
operator unspecified-bool-type() const;
void swap(scopted_ptr & b);
};
auto_ptr : 可以轉讓,同時也失去了管理權。
scopted_array:
template<class T> class scopted_array {
public :
explicit scoped_array(T* p = 0);
~scoped_array();
void reset(T* p =0);
T& operator[] (std::ptrdiff_t i) const;
T* get() const;
operator unspecified-bool-type() const;
void swap(scoped_array& b);
};
shared_ptr;
template<class T> class shared_ptr{
public:
typedef T element_type;
shared_ptr();
shared_ptr(Y * p);//獲得指向類型T的指針P的管理權,同時引用計數器置為1.這個要求Y必須能夠轉換為T類型。
template<class Y> explicit shared_ptr(Y* p);
template<class Y,class D> shared_ptr(Y*p, D d);//行為類似shared_ptr(Y*p),但是使用參數d指定了析構時的定制刪除器。而不是簡單的delete.
~shared_ptr();
shared_ptr(shared_ptr const& r);//從另外一個shared_ptr 獲取指針管理權,同時引用計數加1,結果是兩個shared_ptr共享一個指針管理權。
template<class Y>explicit shared_ptr(std::auto_ptr<Y> & r);//從一個auto_ptr獲得引用計數的管理權,引用計數置為1,同時auto_ptr自動失去管理權.
shared_ptr & operator = (shared_ptr const & r);
template<class Y>shared_ptr & operator = (shared_ptr<Y> const& r);
template<class Y>shared_ptr & operator = (std::auto_ptr<Y> & r);
void reset();//引用計數減少1,停止對指針的共享。
template<class Y> void reset(Y* p);//帶參數的reset,原指針引用計數減少1的同時改為管理另外一個指針。
template<class Y,class D> void reset(Y *p,D d);
T& operator*() const;
T* operator->() const;
T* get() const;
bool unique() const; //
long use_count() const; //
operator unspecified-bool-type() const;
void swap(shared_ptr& b);
};
//////////////////
shared_ptr<int> spi(new int);
assert(spi); //bool 語境中隱式轉換為bool值。
shared_ptr<string> sps(new string("smart"));
shared_ptr不能使用諸如static_cast<T*>(p.get())的形式這將提供了類似轉型函數static_pointer_cast<T>(),const_pointer_cast<T>()和dynamic_pointer_cast<T>(),
他們與標准轉型類似,不過返回的是shared_ptr。
//工廠函數
make_shared<T>() 來消除顯示的調用new。
template<class T, class... Args>
shared_ptr<T> make_shared(Args && ... args); //最多可以接受10個參數。
#include <boost/make_shared.hpp>
int main(){
shared_ptr<string> sp = make_shared<string>("make_shared");
shared_ptr<vector<int> >spv = make_shared<vector<int> >(10,2);
}
橋接模式:就是利用純虛函數在子類中實現。
里式替換原則:任何基類出現的地方,子類一定可以出現。
虛析構函數是為了解決基類的指針指向派生類對象,並用基類的指針刪除派生類對象。
shared_ptr 刪除器:
fg: socket_t *s = open_socket();
shared_ptr<socket_t>p(s,close_socket);//只要傳入刪除器即可
也可以在函數前面加上地址操作符& , shared_ptr<socket_t>p(s,&close_socket);
shared_ptr<void> :就像一個泛型指針容器.擁有容納任意類型的能力。
刪除器的高級用法:
由於空指針可以是任何指針類型,因此share_ptr<void>還可以實現退出作用域時調用任意函數。
void any_function(void *p ){
cout<<“some operation”<<endl;
}
int main(){
shared_ptr<void>p((void*)0,any_function);
}
weak_ptr: shared_ptr的助手. 獲得資源的觀測權,但是沒有共享資源,它的構造不會引起引用計數的增加
template<class T> class weak_ptr
{
plublic :
weak_ptr();
template<class Y>weak_ptr(shared_ptr<Y> const& r);
weak_ptr(weak_ptr const& r);
~weak_ptr();
weak_ptr & operator=(weak_ptr const& r);
long use_count() const;
bool expired() const; //等價於 use_count == 0;
shared_ptr<T> lock() const; //expired()返回true,可以從被觀測的shared_ptr獲得一個可用的對象,從而可以操作資源。
void reset();
void swap(weak_ptr<T> & b);
};
fg:
shared_ptr<int> sp(new int(10));
assert(sp.use_count()==1);
weak_ptr<int>wp(sp);
assert(sp.use_count()==1);
if(!wp.expired()){
shared_ptr<int>sp2=wp.lock();
*sp2 = 100;
assert(wp.use_count() ==2);
}
assert(wp.use_count() == 1);
sp.reset();
assert(wp.expired());
assert(!wp.lock());
獲取this的shared_ptr ;
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
class self_shared: public enable_shared_from_this<self_shared>{
public:
self_shared(int n):x(n){}
int x;
void print(){cout<<"self_shared"<< x <<endl;}
};
int main(){
shared_ptr<self_shared>sp = make_shared<self_shared>(314);
sp->print();
p->x =1000;
}
//intrusive_ptr 侵入式引用計數指針。
//101
pool : 只分配普通數據類型,不能用於類和對象。
template<typename UserAllocator =...>
class pool {
public:
explicit pool(size_type requested_size);
~pool();
size_type get_requested_size() const;
void *malloc();
void *ordered_malloc();
void *ordered_malloc(size_type n);
bool is_from(void * chunk) const;//測試是否是從這個 內存池分出去的。
void free(void *chunk);
void ordered_free(void* chunk);
void ordered_free(void * chunks,size_type n);
bool release_memory();//讓內存池釋放已經未分配的內存,但已經分配的內存不受影響。
bool purge_memory();//強制釋放所有分配的內存。pool的析構就是調用這個,一般不要手動調用。
}
fg:
#include <boost/pool/pool.h>
using namespace std;
int main(){
pool<> p1(sizeof(int));
int *p = (int *)p1.malloc();
assert(p1.is_from(p));
p1.free(p);
for(int i=0;i<100;++i){
p1.ordered_malloc(10);
}
}
棧:函數內部局部變量
堆:new 分配的
自由儲存區:malloc分配的
全局靜態存儲區:全局變量和靜態變量。
常態存儲區:常量,不允許修改。
object_pool :用於類實例(對象)的內存池
#include <boost/poool/object_pool.hpp>
using namespace boost;
template<typename ElementType>
class object_pool: protected pool{
public:
object_pool();
~object_pool();
//malloc 和 free 被調用時不調用構造函數和析構函數,也就是說只操作一塊原始的內存塊。盡量少用。
element_type * malloc();
void free(element_type* p);
bool is_from(element_type *p) const;
element_type * construct(...); //直接在內存池中創建對象。
void destory(element_type* p);
}
#include<boost/pool/object_pool.hpp>
using namespace std;
struct demo_class{
public :
int a,b,c;
demo_class(int x =1, int y =2, int z=3):a(x),b(y),c(z){}
};
int main(){
object_pool<demo_class>p1;
demo_class *p = p1.malloc();
assert(p1.is_from(p));
assert(p->a!=1 || p->b!=2 || p->c != 3); //p都沒有初始化
p = p1.construct(7,8,9);
assert(p->a ==7);
object_pool<string> pls;//連續分配string 對象的內存池。
for(int i=0;i<10;++i){
string *ps = pls.construct("hello object_pool");
cout <<*ps<<endl;
}
}
singleton_pool : 可以分配簡單數據類型(POD)的內存指針,但是它是一個單件,並提供線程安全。不會自動釋放所占空間。除非手動調用release_memory()或purge_memory();
#include <boost/pool/singleton_pool.hpp>
using namespace boost;
template<typename Tag,usigned RequestedSize> // RequestedSize 指示pool分配的大小。
class singleton_pool{
public: static bool is_from(void * ptr);
static void * malloc();
static void * ordered_malloc();
static void * ordered_malloc(size_type n);
static void free(void * ptr);
static void ordered_free(void * ptr);
static void free(void* ptr);
static void ordered_free(void *ptr,size_type n);
static bool release_memory();
static bool purge_memory();
}
單件模式:單件創建分為兩種,一:將一個公共構造函數改為私有的,二是:保留類的公共構造函數,通過一個靜態成員來決定是否返回一個實例。
BOOST_AUTO 的功能與auto 相似。
為無效值提供了一個更好的處理方式:
optional: 包裝可能產生無效值的對象,實現未初始化的概念。<boost/optional.hpp>
#include <boost/optional.hpp>
using namespace boost;
template<class T>
class optional {
public:
optional();
optional(T const& v);
optional(bool condition , T v);
optional & operator = (T const& rhs);
T* operator->();
T& operator*();
T& get();
T* get_ptr();
T const& get_value_or(T const& default) const;
bool operator!() const;
}
/////////////////////////////////
#include <boost/optional.hpp>
using namespace boost;
optional<double> cacl(int x){
return optional<double>(x!=0,1.0/x);
}
optional<double> sqrt_op(double x){
return optional<double>(x>0,sqrt(x));
}
int main(){
optional<double> d = calc(10);
if(d){
cout<<*d<<endl;
}
if(!d){
cout<<"no result"<<endl;
}
}
////////////////////////////////
工廠函數:make_pair(),make_shared(),make_optional():可以根據參數類型自動推導optional的類型,用來輔助創造optional對象。
optional<T> make_optional(T const& v);
optional<T> make_optional(bool condition, T const& v);
make_optional()無法推導出T引用類型的optional對象,因此需要一個optional<T&>的對象,就不能使用make_optional()函數。
#include<boost/optional.hpp>
using namespace std;
int main(){
BOOST_AUTO(x,make_optional(5)));
assert(*x == 5);
BOOST_AUTO(y,make_optional<double>((*x>10),1.0));
assert(!y);
}
optional<T> 要求類型T 具有拷貝意義,因為內部會保存值的拷貝,但是有時候拷貝的代價會很高。是種浪費,因此有了optional就地創建
in_place_factory.
#include <boost/optional.hpp>
#include <boost/utility/im_place_factory.hpp>
using namespace boost;
int main(){
// 就地創建string對象,不要臨時對象string.
optional<string> ops(in_place("test in_place_factory"));
cout<<*ops<<endl;
}
boost 賦值: assign;
int main(){
using namespace boost::assign;//啟用assign庫的功能。
vector<int> v;
v += 1,2,3,4,5,6*6;
set<string> s;
s += "cpp","java","c#","python";
map<int,string>m;
m+= make_pair(1,"one"),make_pair(2,"two");
}
operator += 僅限於應用STL中定義的標准容器。
operator() 提供了更加通用的解決方案。不能直接使用operate(),應當使用assign庫提供的三個輔助函數insert(),push_front(),push_back().返回一個代理
對象list_inserter.
#include <boost/assign.hpp>
int main(){
using namespace boost::assign;
vertor<int> v;
push_back(v)(1)(2)(3);
list<string> l;
push_front(l)("cpp")("java")("c#");
set<double>s;
insert(s)(3.14)(0.618);
map<int,string>m;
insert(m)(1,"one")(2,"two");
}
對於擁有push_back()或push_front()成員函數的容器(vertor,list),可以調用assign::push_back()或者assign::push_front,
而對於set和map,則只能使用assign::insert().
初始化容器元素:
list_of() 函數的用法與之前的insert(),push_back()等函數,也重載了括號,逗號操作符。很智能。
減少重復輸入:
template<class U>
generic_list& repeat(std::size_t sz, U u);
template<class Nullary_function>
generic_list& repeat_fun(std::size_t sz,Nullary_function fun);
template<class SinglePassIterator>
generic_list& range(SinglePassIterator first, SinglePassIterator last);
template<class SinglePassRange >
generic_list& range(const SinglePassRange& r);
單件模式:
boost.pool的單件實現。
singleton_default.
template<typename T>
struct singleton_default {
public :
typedef T object_type;
static object_type & instance();
}
fg:
#include <boost/pool/detail/singleton.hpp>
using boost::details::pool::singleton_default;
class point{
public:
point(int a=0,int b=0,int c=0):x(a),y(b),z(c){
cout<<"point ctor"<<endl;
}
~point(){
cout<<"point dtor"<<endl;
}
};
int main(){
cout<<"main start"<<endl;
typedef singleton_default<point> origin;
origin::instance.print();
}
boost.serialzation的單件實現
在序列庫serialization中另一個單件實現類:singleton.位於 boost::serialization.
singleton:
template<typename T>
class singleton: public boost::noncopyable{
public:
static const T& get_const_instance();
static T& get_mutable_instance();
}
兩種用法:
一:
#include<boost/serialization/singleton.hpp>
using boost::serialization::singleton;
class point{...}
int main(){
cout<<"main start"<<endl;
typedef singleton<point> origin;
origin::get_const_instance().print();
origin::get_mutable_instance().print();
cout<<"main() finished"<<endl;
}
二:通過繼承的方式。
#include<boost/serialization/singleton.hpp>
using boost::serialization::singleton;
class point : public singleton<point> {...} //注意這里
int main(){
cout<<"main start"<<endl;
typedef singleton<point> origin;
origin::get_const_instance().print();
origin::get_mutable_instance().print();
cout<<"main() finished"<<endl;
}
tribool:三態的布爾邏輯。
字符串與文本處理:
lexical_cast
並發編程:
mutex: 獨占式互斥量
try_mutex
timed_mutex : 也是獨占試互斥量,但提供超時鎖定功能。
recursive_mutex 遞歸式互斥量,可以多次鎖定。相應的也要多次解鎖。
recursive_try_mutex
recursive_timed_mutex 遞歸是互斥量
shared_mutex: multiple-reader/single-writer型共享互斥量。
loack_guard 他們在構造時鎖定互斥量,在析構時自動解鎖。
basic_atom:
template <typename T>
class basic_atom: noncopyable{
private:
T n;
typedef mutex mutex_t;
mutex_t mu;
public :
T operator ++ (){
mutex_t::scoped_lock lock(mu);
return ++n;
}
operator T(){
return n;
}
}
typedef basic_atom<int> atom_int;
atom_int x;
cout<<++x;
join() :一直阻塞等待。
timed_join() 阻塞等待線程結束。或者阻塞一定的時間段,然后不管線程是否結束都返回。
detach() 線程執行體分離,但是線程會繼續執行。
yield() 指示當前線程放棄時間片,允許其他的線程執行。
bind:可以把庫函數所需的參數綁定到一個函數對象中,而function則可以存儲bind表達式的結果,
interrupt():中斷正在被執行的線程。
bind:
bind(f,1,2) => f(1,2)
bind(f,_1,5)(x) => f(x,5);
如果想傳入變量的引用。
int i=5;
bind(f,ref(i),_1);
bind(f,cref(i),1);
bind<int>(f,_1,_1)(x) 有些編譯器不支持這個用法。
boost::bind(boost::type<int>(),f,_1,_1)(x)
通過pointers to members使用bind
bind將傳入的成員(數據成員和成員函數)指針作為第一個參數,其行為如同使用boost::mem_fn將成員指針轉換為一個函數對象,即:
bind(&X::f, args); 等價於bind<R>(mem_fn(&X::f), args),其中R為X::f的返回類型(成員函數)或類型(數據成員)。
bind中的第一個參數不參與計算過程,假設如下程序想要實現對於向量v中的每個函數指針,傳入一個參數 5:
typedef void (*pf)(int);
std::vector<pf> v;
std::for_each(v.begin(), v.end(), bind(_1, 5));
上述程序並沒有實現我們想要的結果:可以通過使用一個幫助函數對象apply,該對象可以將bind的第一個參數作為一個函數對象,如下:
typedef void (*pf)(int);
std::vector<pf> v;
std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5));
thread 庫在字命名空間this_thread提供了一組函數和類共同完成線程的中斷啟用和禁用。
線程組:
thread 提供thread_group用於管理一組線程。就像一個線程池。
條件變量:
thread 庫提供的另一種等待的同步機制,可以實現線程的通信,它必須與互斥量配合使用,等待另外一個線程中某個事件的發生,然后線程才能繼續執行。
thread: condition_variable 和 condition_variable_any,一般情況下使用condition_varible_any。
緩沖區buffer 使用了兩個變量cond_put 和 cond_get() 的處理流程與cond_put類似。
#include <stack>
class buffer{
private:
mutex mu;
condition_variable_any cond_put;
condition_variable_any cond_get;
stack<int> stk;
int un_read,capacity;
bool is_full(){
return un_read == capacity;
}
bool is_empty(){
return un_read == 0;
}
public:
buffer(size_t n):un_read(0),capacity(n){}
void put(int x){
{
mutex::scoped_lock lock(mu);
while(is_full){
{
mutex_t::scoped_lock lock(io_mu);
cout<<"full waiting..."<<endl;
}
cond_put.wait(mu);
}
stk.push(x);
++un_read;
}
cond_get.notify_one();
}
void get(int *x){
{
mutex::scoped_lock lock(mu);
while(is_empty()){
{
mutex::scoped_lock(io_mu);
cout<<"empty waiting"<<endl;
}
cond_get.wait(mu);
}
--un_read;
*x = stk.top();
stk.pop();
}
cond_put.notify_one();
}
};
共享互斥量:
shared_mutex 不同於mutex和recursive_mutex,它允許線程獲取多個共享所有權和一個專享所有權,實現讀寫機制,即多個線程讀一個線程寫。
讀線程時:shared_lock<shared_mutex> 寫線程時:unique_lock<shared_mutex>.
future; 在很多情況下線程不僅僅要工作還要執行工作,他還可能返回一些計算結果。
funture 使用packaged_task 和 promise 兩個模版類來包裝異步調用。unique_future 和 shared_future來獲取異步調用結果。
future 還提供wait_for_any() 和 wait_for_all()
僅初始化一次:
使多個線程在操作初始化函數時只能有一個線程成功執行。
once_flag of = BOOST_INIT;
void call_func(){
call_once(of,init_count);
}
barrier: 是thread基於條件變量的另一種同步機制,可以用於多個線程同步。當線程執行到barrier時必須要等待,直到所有的線程都到達這個點時才能繼續執行。
智能所:boost::mutex::scoped_lock.
線程本地存儲:
有時候函數使用了局部變量或者全局變量,因此不能用於多線程,因為無法保證靜態變量在線程環境下重入時是否正確。
thread庫使用了thread_specific_ptr實現了可移植的線程本地存儲機制。
thread_specific_ptr 智能指針。
定時器:
deadline_timer有兩種形式的構造函數,都要求有一個io_service 對象,用於提交IO請求,第二個是定時器的終止時間,可以是posix_time。