青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

colorful

zc qq:1337220912

 

shared_from_this 幾個值得注意的地方

shared_from_this()是 enable_shared_from_this<T>的成員 函數,返回shared_ptr<T>。首先需要注意的是,這個函數僅在shared_ptr<T>的構造函數被調用之后才能使 用。原因是enable_shared_from_this::weak_ptr并不在構造函數中設置,而是在shared_ptr<T>的 構造函數中設置。

如下代碼是錯誤的:
  1. class D:public boost::enable_shared_from_this<D>
  2. {
  3. public:
  4.     D()
  5.     {
  6.         boost::shared_ptr<D> p=shared_from_this();
  7.     }
  8. };
復制代碼
原 因很簡單,在D的構造函數中雖然可以保證enable_shared_from_this<D>的構造函數已經被調用,但正如前面所 說,weak_ptr還沒有設置。

如下代碼也是錯誤的:
  1. class D:public boost::enable_shared_from_this<D>
  2. {
  3. public:
  4.     void func()
  5.     {
  6.         boost::shared_ptr<D> p=shared_from_this();
  7.     }
  8. };
  9. void main()
  10. {
  11.     D d;
  12.     d.func();
  13. }
復制代碼
錯 誤原因同上。

如下代碼是正確的:
  1. void main()
  2. {
  3.     boost::shared_ptr<D> d(new D);
  4.     d->func();
  5. }
復制代碼
這 里boost::shared_ptr<D> d(new D)實際上執行了3個動作:首先調用enable_shared_from_this<D>的構造函數;其次調用D的構造函數;最后調用 shared_ptr<D>的構造函數。是第3個動作設置了enable_shared_from_this<D>的 weak_ptr,而不是第1個動作。這個地方是很違背c++常理和邏輯的,必須小心。

結論是,不要在構造函數中使用shared_from_this;其次,如果要使用shared_ptr,則應該 在所有地方均使用,不能使用D d這種方式,也決不要傳遞裸指針。   

另一個值得注意的地方是在類的繼承樹中不能有2個或更多個enable_shared_from_this<T>。例如如下代碼是錯誤的:
  1. class A:public boost::enable_shared_from_this<A>
  2. {
  3. public:
  4.     A():a(1){}
  5.     virtual ~A(){}
  6.     boost::shared_ptr<A> get_ptra(){return shared_from_this();}
  7.     int a;
  8. };
  9. class B:public A,public boost::enable_shared_from_this<B>
  10. {
  11. public:
  12.     B():b(2){}
  13.     boost::shared_ptr<B> get_ptrb()
  14.     {
  15.         return boost::enable_shared_from_this<B>::shared_from_this();
  16.     }
  17.     int b;
  18. };
  19. int _tmain(int argc, _TCHAR* argv[])
  20. {
  21.     {
  22.         boost::shared_ptr<B> x(new B);
  23.         boost::shared_ptr<A> a1 = x->get_ptra();
  24.         boost::shared_ptr<B> b1 = x->get_ptrb();
  25.     }
  26.     return 0;
  27. }
復制代碼
注 意上面代碼中,B同時擁有2個enable_shared_from_this的基類,一個是 enable_shared_from_this<A>,另一個是enable_shared_from_this<B>。在 boost::shared_ptr<B> x(new B);這行代碼中,shared_ptr<B>的構造函數僅會設置2個基類中的一個的weak_ptr。在上面的例子中,僅設置 enable_shared_from_this<A>的。如果修改B的定義為:

class B:public boost::enable_shared_from_this<B>,public A,

則僅設置enable_shared_from_this<B>的weak_ptr。很明顯都是錯誤的。

那么enable_shared_from_this以及shared_ptr為何要如此實現呢?又為什么會有如此怪異的結果呢?

首先考察shared_ptr的構造函數:
  1. template<class Y>
  2. explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
  3. {
  4.     boost::detail::sp_enable_shared_from_this( pn, p, p );
  5. }
  6. template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this<T> const * pe, Y const * px )
  7. {
  8.     if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
  9. }
復制代碼
注 意這個sp_enable_shared_from_this是一個模板函數,而且僅調用了一次,所以不可能2個 enable_shared_from_this基類的weak_ptr都被賦值。但問題在于,在調換了B的定義之后結果居然是不一樣的。這里有一個很隱 秘的編譯器BUG。按道理來說,編譯器在編譯這段代碼時,應該注意到無法真正決斷該怎么實例化sp_enable_shared_from_this并且 報一個錯,但vc 2008并沒有報錯,而是通過編譯了。(g++會在此處報錯)

那么正確的解法是怎樣的呢?
  1. class B:public A
  2. {
  3. public:
  4.     B():b(2){}
  5.     boost::shared_ptr<B> get_ptrb()
  6.     {
  7.         return boost::dynamic_pointer_cast<B>(shared_from_this());
  8.     }
  9.     int b;
  10. };
復制代碼
注 意到這里B并沒有直接繼承enable_shared_from_this,而是使用dynamic_pointer_cast進行了類型轉換。

關于為什么enable_shared_from_this是這樣實現的,可以參看作者原文:

Every enable_shared_from_this base contains a weak_ptr, The shared_ptr constructor looks up the enable_shared_from_this base and initializes its weak_ptr accordingly. This doesn't work when there are
two or more enable_shared_from_this bases, though.

I could put the weak_ptr in a virtual polymorphic base. This would force polymorphism on all clients of enable_shared_from_this... probably acceptable. It will also force a dynamic_pointer_cast in every
shared_from_this, and this may be harder to swallow, particularly in cases where RTTI is off. So I'm not sure.

If you do want the above behavior, it's easy to duplicate, as I already responded in my first post on the topic. Just make FooB return dynamic_pointer_cast<B>( FooA() ) and remove the enable_shared_from_this<B>
base (A needs to be made polymorphic, of course).

注意為了讓dynamic_pointer_cast能工作,A必須具有虛函數,那么最簡單的做法當然是令其析構函 數為虛函數(通常一個class如果希望被繼承,析構函數就應該為虛函數)

posted @ 2012-06-22 22:42 多彩人生 閱讀(644) | 評論 (0)編輯 收藏

enable_shared_from_this(轉載)

在 C++ 中需要自己來處理內存,稍微處理不當,就會存在非常郁悶的內存泄漏問題

 

還好,現在 C++ 中推出了強大的智能指針,即 smart_ptr ,本文先稍微介紹一下 smart_ptr ,然后具體說說 shared_ptr 和 weak_ptr ,特別是 enable_shared_from_this 和 shared_from_this

 

除了標準庫中的 auto_ptr 之外

在 boost 或者 tr1 中的 smart_ptr 主要是有下面幾種

  • scoped_ptr
  • scoped_array
  • shared_ptr
  • shared_array
  • intrusive_ptr
  • weak_ptr

這些里面最難理解的是綜合應用了 weak_ptr 和 shared_ptr 的 enable_shared_from_this 類,在該類中定了成員函數 shared_from_this() ,返回 shared_ptr<T> 。這個函數僅在 shared_ptr<T> 的構造函數被調用之后才能使用。原因是 enable_shared_from_this::weak_ptr 并不在構造函數中設置(此處的構造函數指的是類型 T 的構造函數),而是在 shared_ptr<T> 的構造函數中設置(此處的構造函數指的是類型 shared_ptr<T> 的構造函數)。

 

在下面的代碼中:

 

Cpp代碼
  1. #include <iostream>   
  2.   
  3. #include <string>   
  4.   
  5.     
  6.   
  7. #include <boost/shared_ptr.hpp>   
  8.   
  9. #include <boost/weak_ptr.hpp>   
  10.   
  11. #include <boost/enable_shared_from_this.hpp>   
  12.   
  13.     
  14.   
  15. using namespace std;   
  16.   
  17.     
  18.   
  19. struct Ansible   
  20.   
  21.   : public boost::enable_shared_from_this<Ansible>   
  22.   
  23. {   
  24.   
  25.     boost::shared_ptr<Ansible> get_shared()   
  26.   
  27.     {   
  28.   
  29.         boost::shared_ptr<Ansible> r(this);   
  30.   
  31.     
  32.   
  33.         return r;   
  34.   
  35.     }   
  36.   
  37.     
  38.   
  39.     ~Ansible()   
  40.   
  41.     {   
  42.   
  43.         cout<<"Destructor"<<endl;   
  44.   
  45.     }   
  46.   
  47. };   
  48.   
  49.     
  50.   
  51. int main(int argc,char* argv[])   
  52.   
  53. {   
  54.   
  55.     boost::shared_ptr<Ansible> a(new Ansible);   
  56.   
  57.     Ansible& r = *a;   
  58.   
  59.     //boost::shared_ptr<Ansible> b = r.get_shared();   
  60.   
  61.     boost::shared_ptr<Ansible> b = r.shared_from_this();   
  62.   
  63.     
  64.   
  65.     cout<<"Reference Number "<<a.use_count()<<" "<<b.use_count()<<endl;   
  66.   
  67.     
  68.   
  69.     return 0;   
  70.   
  71. }  
#include <iostream> #include <string> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <boost/enable_shared_from_this.hpp> using namespace std; struct Ansible : public boost::enable_shared_from_this<Ansible> { boost::shared_ptr<Ansible> get_shared() { boost::shared_ptr<Ansible> r(this); return r; } ~Ansible() { cout<<"Destructor"<<endl; } }; int main(int argc,char* argv[]) { boost::shared_ptr<Ansible> a(new Ansible); Ansible& r = *a; //boost::shared_ptr<Ansible> b = r.get_shared(); boost::shared_ptr<Ansible> b = r.shared_from_this(); cout<<"Reference Number "<<a.use_count()<<" "<<b.use_count()<<endl; return 0; }

 

若不使用 shared_from_this() 成員函數,則會輸出 a 和 b 的 use_count() 都為 1 ,然后調用 2 次類型 Ansible 的析構函數,若添加了該成員函數,在 a 和 b 的 use_count() 輸出為 2 ,只是調用一次 Ansible 的析構函數。原因是 enable_shared_from_this 里面在 shared_ptr<T> 的時候構造了一個 weak_ptr 類,而 weak_ptr 只是監視,不增加引用計數

 

(下面是轉載: http://huyuguang1976.spaces.live.com/blog/cns!2A9E272E3C33AFF1!185.entry

所以如下代碼是錯誤的:

 

class D:public boost::enable_shared_from_this<D>

{

public:

    D()

    {

        boost::shared_ptr<D> p=shared_from_this();

    }

};

 

原因很簡單,在 D 的構造函數中雖然可以保證 enable_shared_from_this<D> 的構造函數已經被調用,但正如前面所說, weak_ptr 還沒有設置。

 

如下代碼也是錯誤的:

 

class D:public boost::enable_shared_from_this<D>

{

public:

    void func()

    {

        boost::shared_ptr<D> p=shared_from_this();

    }

};

 

void main()

{

    D d;

    d.func();

}

 

錯誤原因同上。

 

如下代碼是正確的:

 

void main()

{

    boost::shared_ptr<D> d(new D);

    d->func();

}

 

這里 boost::shared_ptr<D> d(new D) 實際上執行了 3 個動作:首先調用 enable_shared_from_this<D> 的構造函數;其次調用 D 的構造函數;最后調用 shared_ptr<D> 的構造函數。是第 3 個動作設置了 enable_shared_from_this<D> 的 weak_ptr ,而不是第 1 個動作。這個地方是很違背 c++ 常理和邏輯的,必須小心。

 

結論是,不要在構造函數中使用 shared_from_this ;其次,如果要使用 shared_ptr ,則應該在所有地方均使用,不能使用 D d 這種方式,也決不要傳遞裸指針。


另解:::::
struct X

{

         boost::shared_ptr<X> getX()

{

         boost::shared_ptr<X> r ;//????如何實現

         return r;

}

};

 

要得到X的智能指針,只是在對象指針是受shared_ptr保護的基礎上的,舉例如下:

void test_X()

{

         {

X x;

                  boost::shared_ptr<X> px = x.getX();//錯誤

}

         {

X* x = new X();

boost::shared_ptr<X> px = x->getX();//錯誤

}

         {

boost::shared_ptr<X>  x (new X());

boost::shared_ptr<X> px = x->getX();//正確

}

}

posted @ 2012-06-22 22:41 多彩人生 閱讀(500) | 評論 (0)編輯 收藏

stl string常用函數

string類的構造函數:
string(const char *s); //用c字符串s初始化
string(int n,char c); //用n個字符c初始化
此外,string類還支持默認構造函數和復制構造函數,如string s1;string s2="hello";都是正確的寫法。當構造的string太長而無法表達時會拋出length_error異常

string類的字符操作:
const char &operator[](int n)const;
const char &at(int n)const;
char &operator[](int n);
char &at(int n);
operator[]和at()均返回當前字符串中第n個字符的位置,但at函數提供范圍檢查,當越界時會拋出out_of_range異常,下標運算符[]不提供檢查訪問。
const char *data()const;//返回一個非null終止的c字符數組
const char *c_str()const;//返回一個以null終止的c字符串
int copy(char *s, int n, int pos = 0) const;//把當前串中以pos開始的n個字符拷貝到以s為起始位置的字符數組中,返回實際拷貝的數目

string的特性描述:
int capacity()const; //返回當前容量(即string中不必增加內存即可存放的元素個數)
int max_size()const; //返回string對象中可存放的最大字符串的長度
int size()const; //返回當前字符串的大小
int length()const; //返回當前字符串的長度
bool empty()const; //當前字符串是否為空
void resize(int len,char c);//把字符串當前大小置為len,并用字符c填充不足的部分

string類的輸入輸出操作:
string類重載運算符operator
>>用于輸入,同樣重載運算符operator<<用于輸出操作。
函數getline(istream
&in,string &s);用于從輸入流in中讀取字符串到s中,以換行符'\n'分開。

string的賦值:
string &operator=(const string &s);//把字符串s賦給當前字符串
string &assign(const char *s);//用c類型字符串s賦值
string &assign(const char *s,int n);//用c字符串s開始的n個字符賦值
string &assign(const string &s);//把字符串s賦給當前字符串
string &assign(int n,char c);//用n個字符c賦值給當前字符串
string &assign(const string &s,int start,int n);//把字符串s中從start開始的n個字符賦給當前字符串
string &assign(const_iterator first,const_itertor last);//把first和last迭代器之間的部分賦給字符串

string的連接:
string &operator+=(const string &s);//把字符串s連接到當前字符串的結尾
string &append(const char *s); //把c類型字符串s連接到當前字符串結尾
string &append(const char *s,int n);//把c類型字符串s的前n個字符連接到當前字符串結尾
string &append(const string &s); //同operator+=()
string &append(const string &s,int pos,int n);//把字符串s中從pos開始的n個字符連接到當前字符串的結尾
string &append(int n,char c); //在當前字符串結尾添加n個字符c
string &append(const_iterator first,const_iterator last);//把迭代器first和last之間的部分連接到當前字符串的結尾

string的比較:
bool operator==(const string &s1,const string &s2)const;//比較兩個字符串是否相等
運算符">","<",">=","<=","!="均被重載用于字符串的比較;
int compare(const string &s) const;//比較當前字符串和s的大小
int compare(int pos, int n,const string &s)const;//比較當前字符串從pos開始的n個字符組成的字符串與s的大小
int compare(int pos, int n,const string &s,int pos2,int n2)const;//比較當前字符串從pos開始的n個字符組成的字符串與s中pos2開始的n2個字符組成的字符串的大小
int compare(const char *s) const;
int compare(int pos, int n,const char *s) const;
int compare(int pos, int n,const char *s, int pos2) const;
compare函數在
>時返回1,<時返回-1==時返回0

string的子串:
string substr(int pos = 0,int n = npos) const;//返回pos開始的n個字符組成的字符串


string的交換:
void swap(string &s2); //交換當前字符串與s2的值

string類的查找函數:

int find(char c, int pos = 0) const;//從pos開始查找字符c在當前字符串的位置
int find(const char *s, int pos = 0) const;//從pos開始查找字符串s在當前串中的位置
int find(const char *s, int pos, int n) const;//從pos開始查找字符串s中前n個字符在當前串中的位置
int find(const string &s, int pos = 0) const;//從pos開始查找字符串s在當前串中的位置
//查找成功時返回所在位置,失敗返回string::npos的值

int rfind(char c, int pos = npos) const;//從pos開始從后向前查找字符c在當前串中的位置
int rfind(const char *s, int pos = npos) const;
int rfind(const char *s, int pos, int n = npos) const;
int rfind(const string &s,int pos = npos) const;
//從pos開始從后向前查找字符串s中前n個字符組成的字符串在當前串中的位置,成功返回所在位置,失敗時返回string::npos的值

int find_first_of(char c, int pos = 0) const;//從pos開始查找字符c第一次出現的位置
int find_first_of(const char *s, int pos = 0) const;
int find_first_of(const char *s, int pos, int n) const;
int find_first_of(const string &s,int pos = 0) const;
//從pos開始查找當前串中第一個在s的前n個字符組成的數組里的字符的位置。查找失敗返回string::npos

int find_first_not_of(char c, int pos = 0) const;
int find_first_not_of(const char *s, int pos = 0) const;
int find_first_not_of(const char *s, int pos,int n) const;
int find_first_not_of(const string &s,int pos = 0) const;
//從當前串中查找第一個不在串s中的字符出現的位置,失敗返回string::npos

int find_last_of(char c, int pos = npos) const;
int find_last_of(const char *s, int pos = npos) const;
int find_last_of(const char *s, int pos, int n = npos) const;
int find_last_of(const string &s,int pos = npos) const;

int find_last_not_of(char c, int pos = npos) const;
int find_last_not_of(const char *s, int pos = npos) const;
int find_last_not_of(const char *s, int pos, int n) const;
int find_last_not_of(const string &s,int pos = npos) const;
//find_last_of和find_last_not_of與find_first_of和find_first_not_of相似,只不過是從后向前查找

string類的替換函數:

string &replace(int p0, int n0,const char *s);//刪除從p0開始的n0個字符,然后在p0處插入串s
string &replace(int p0, int n0,const char *s, int n);//刪除p0開始的n0個字符,然后在p0處插入字符串s的前n個字符
string &replace(int p0, int n0,const string &s);//刪除從p0開始的n0個字符,然后在p0處插入串s
string &replace(int p0, int n0,const string &s, int pos, int n);//刪除p0開始的n0個字符,然后在p0處插入串s中從pos開始的n個字符
string &replace(int p0, int n0,int n, char c);//刪除p0開始的n0個字符,然后在p0處插入n個字符c
string &replace(iterator first0, iterator last0,const char *s);//把[first0,last0)之間的部分替換為字符串s
string &replace(iterator first0, iterator last0,const char *s, int n);//把[first0,last0)之間的部分替換為s的前n個字符
string &replace(iterator first0, iterator last0,const string &s);//把[first0,last0)之間的部分替換為串s
string &replace(iterator first0, iterator last0,int n, char c);//把[first0,last0)之間的部分替換為n個字符c
string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last);//把[first0,last0)之間的部分替換成[first,last)之間的字符串

string類的插入函數:

string &insert(int p0, const char *s);
string &insert(int p0, const char *s, int n);
string &insert(int p0,const string &s);
string &insert(int p0,const string &s, int pos, int n);
//前4個函數在p0位置插入字符串s中pos開始的前n個字符
string &insert(int p0, int n, char c);//此函數在p0處插入n個字符c
iterator insert(iterator it, char c);//在it處插入字符c,返回插入后迭代器的位置
void insert(iterator it, const_iterator first, const_iterator last);//在it處插入[first,last)之間的字符
void insert(iterator it, int n, char c);//在it處插入n個字符c

string類的刪除函數

iterator erase(iterator first, iterator last);
//刪除[first,last)之間的所有字符,返回刪除后迭代器的位置
iterator erase(iterator it);//刪除it指向的字符,返回刪除后迭代器的位置
string &erase(int pos = 0, int n = npos);//刪除pos開始的n個字符,返回修改后的字符串

string類的迭代器處理:

string類提供了向前和向后遍歷的迭代器iterator,迭代器提供了訪問各個字符的語法,類似于指針操作,迭代器不檢查范圍。
用string::iterator或string::const_iterator聲明迭代器變量,const_iterator不允許改變迭代的內容。常用迭代器函數有:
const_iterator begin()
const;
iterator begin();
//返回string的起始位置
const_iterator end()const;
iterator end();
//返回string的最后一個字符后面的位置
const_iterator rbegin()const;
iterator rbegin();
//返回string的最后一個字符的位置
const_iterator rend()const;
iterator rend();
//返回string第一個字符位置的前面
rbegin和rend用于從后向前的迭代訪問,通過設置迭代器string::reverse_iterator,string::const_reverse_iterator實現

字符串流處理:

通過定義ostringstream和istringstream變量實現,
<sstream>頭文件中
例如:
string input("hello,this is a test");
istringstream
is(input);
string s1,s2,s3,s4;
is>>s1>>s2>>s3>>s4;//s1="hello,this",s2="is",s3="a",s4="test"
ostringstream os;
os
<<s1<<s2<<s3<<s4;
cout
<<os.str();

posted @ 2012-06-20 11:16 多彩人生 閱讀(250) | 評論 (0)編輯 收藏

文本模式 二進制模式& 文本文件 二進制文件

這幾個概念很常見但是也容易搞混。前兩者是相反的意思,后兩者是一對。

1. 文本模式(textmode)和二進制模式(binarymode)的區別

0.  無論你用哪種語言進行程序設計,也無論你用哪個函數進行文件操作(庫函數也好,直接操作系統API也好),最終的文件打開的操作都是由操作系統來進行的,因此各種語言的情況從本質上來說都是相同的。用二進制模式打開一個文件的時候,文件本身的內容和你編寫程序時用函數讀到的內容完全相同(或者說和磁盤上的內容完全相同)。但是如果用了文本模式,那么操作系統在將文件內容傳給上層程序(庫函數,或者是你的程序)時,或者上層程序通過操作系統向文件寫入內容時,操作系統都會預先進行一層預處理(或者說轉義),具體過程依賴于操作系統的實現。

1.  在unix(包括linux)系統上,一個程序從文件里讀數據,它得到的數據就是數據本身,一個一個的字節。然而在windows系統上,一個文件可以 用兩種模式打開,二進制模式或者文本模式,在二進制模式下,表現的就像unix系統;然而在文本模式下,會有一個轉換。是\n <-------> \r\n之間的轉換。具體講就是將回車符"\r\n"解釋成"\n"(讀出時),將"\n"解釋成"\r\n"(寫入時)。總之,在unix系統上,打開文件只有二進制模式,在windows系統上,打開文件有文本模式和二進制模式兩種。

2.文本文件與二進制文件的區別:

將文件看作是由一個一個字節(byte) 組成的, 那么文本文件中的每個字節的最高位都是0,也就是說文本文件使用了一個字節中的七位來表示所有的信息,而二進制文件則是將字節中的所有位都用上了。這就是兩者的區別;接著,第二個問題就是文件按照文本方式或者二進制方式打開,兩者會有什么不同呢?其實不管是二進制文件也好,還是文本文件也好,都是一連串的01,但是打開方式不同,對于這些01的處理也就不同。如果按照文本方式打開,在打開的時候會進行translate,將每個字節轉換成ASCII碼,而以按照二進制方式打開的話,則不會進行任何的translate;最后就是文本文件和二進制文件在編輯的時候,使用的方式也是不同的。譬如,你在記事本中進行文本編輯的時候,你進行編輯的最小單位是字節(byte);而對二進制文件進行編輯的話,最小單位則是位(bit),當然我們都不會直接通過手工的方式對二進制文件進行編輯了。

從文件編碼的方式來看,文件可分為ASCII碼文件和二進制碼文件兩種:
ASCII
文件也稱為文本文件,這種文件在磁盤中存放時每個字符對應一個字節,用于存放對應的ASCII碼。例如,數5678的存儲形式為: 
ASCII
碼: 00110101 00110110 00110111 00111000 
                     ↓          
 ↓      ↓         
  
十進制碼:    5     6         7       

共占用4個字節。ASCII碼文件可在屏幕上按字符顯示,例如源程序文件就是ASCII文件,用DOS命令TYPE可顯示文件的內容。由于是按字符顯示,因此能讀懂文件內容。

二進制文件是按二進制的編碼方式來存放文件的。例如,數5678的存儲形式為:00010110 00101110 只占二個字節。二進制文件雖然也可在屏幕上顯示,但其內容無法讀懂。C系統在處理這些文件時,并不區分類型,都看成是字符流,按字節進行處理。輸入輸出字符流的開始和結束只由程序控制而不受物理符號(如回車符)的控制。因此也把這種文件稱作流式文件 

posted @ 2012-06-17 22:51 多彩人生 閱讀(605) | 評論 (0)編輯 收藏

為數據庫建立索引

最普通的情況,是為出現在where子句的字段建一個索引。為方便講述,我們先建立一個如下的表。
CREATE TABLE mytable (
 id serial primary key,
 category_id int not null default 0,
 user_id int not null default 0,
 adddate int not null default 0
);
如果你在查詢時常用類似以下的語句:
 SELECT * FROM mytable WHERE category_id=1;
最直接的應對之道,是為category_id建立一個簡單的索引:
 CREATE INDEX mytable_categoryid
 ON mytable (category_id);
OK.如果你有不止一個選擇條件呢?例如:
 SELECT * FROM mytable WHERE category_id=1 AND user_id=2;
你的第一反應可能是,再給user_id建立一個索引。不好,這不是一個最佳的方法。你可以建立多重的索引。
CREATE INDEX mytable_categoryid_userid ON mytable (category_id,user_id);
注意到我在命名時的習慣了嗎?我使用"表名_字段1名_字段2名"的方式。你很快就會知道我為什么這樣做了。
現在你已經為適當的字段建立了索引,不過,還是有點不放心吧,你可能會問,數據庫會真正用到這些索引嗎?測試一下就OK,對于大多數的數據庫來說,這是很容易的,只要使用EXPLAIN命令:
EXPLAIN
 SELECT * FROM mytable
WHERE category_id=1 AND user_id=2;
 This is what Postgres 7.1 returns (exactly as I expected)
 NOTICE: QUERY PLAN:
 Index Scan using mytable_categoryid_userid on
 mytable (cost=0.00..2.02 rows=1 width=16)
EXPLAIN
以上是postgres的數據,可以看到該數據庫在查詢的時候使用了一個索引(一個好開始),而且它使用的是我創建的第二個索引。看到我上面命名的好處了吧,你馬上知道它使用適當的索引了。

接著,來個稍微復雜一點的,如果有個ORDER BY字句呢?不管你信不信,大多數的數據庫在使用order by的時候,都將會從索引中受益。
 SELECT * FROM mytable
WHERE category_id=1 AND user_id=2
 ORDER BY adddate DESC;

很簡單,就象為where字句中的字段建立一個索引一樣,也為ORDER BY的字句中的字段建立一個索引:
 CREATE INDEX mytable_categoryid_userid_adddate
 ON mytable (category_id,user_id,adddate);
 注意: "mytable_categoryid_userid_adddate" 將會被截短為
"mytable_categoryid_userid_addda"
 CREATE
 EXPLAIN SELECT * FROM mytable
WHERE category_id=1 AND user_id=2
 ORDER BY adddate DESC;
 NOTICE: QUERY PLAN:
 Sort (cost=2.03..2.03 rows=1 width=16)
-> Index Scan using mytable_categoryid_userid_addda
 on mytable (cost=0.00..2.02 rows=1 width=16)
 EXPLAIN
看看EXPLAIN的輸出,數據庫多做了一個我們沒有要求的排序,這下知道性能如何受損了吧,看來我們對于數據庫的自身運作是有點過于樂觀了,那么,給數據庫多一點提示吧。
為 了跳過排序這一步,我們并不需要其它另外的索引,只要將查詢語句稍微改一下。這里用的是postgres,我們將給該數據庫一個額外的提示--在 ORDER BY語句中,加入where語句中的字段。這只是一個技術上的處理,并不是必須的,因為實際上在另外兩個字段上,并不會有任何的排序操作,不過如果加 入,postgres將會知道哪些是它應該做的。
 EXPLAIN SELECT * FROM mytable
WHERE category_id=1 AND user_id=2
 ORDER BY category_id DESC,user_id DESC,adddate DESC;
 NOTICE: QUERY PLAN:
 Index Scan Backward using
mytable_categoryid_userid_addda on mytable
 (cost=0.00..2.02 rows=1 width=16)
 EXPLAIN
現在使用我們料想的索引了,而且它還挺聰明,知道可以從索引后面開始讀,從而避免了任何的排序。
以 上說得細了一點,不過如果你的數據庫非常巨大,并且每日的頁面請求達上百萬算,我想你會獲益良多的。不過,如果你要做更為復雜的查詢呢,例如將多張表結合 起來查詢,特別是where限制字句中的字段是來自不止一個表格時,應該怎樣處理呢?我通常都盡量避免這種做法,因為這樣數據庫要將各個表中的東西都結合 起來,然后再排除那些不合適的行,搞不好開銷會很大。
如果不能避免,你應該查看每張要結合起來的表,并且使用以上的策略來建立索引,然后再用EXPLAIN命令驗證一下是否使用了你料想中的索引。如果是的話,就OK。不是的話,你可能要建立臨時的表來將他們結合在一起,并且使用適當的索引。
要注意的是,建立太多的索引將會影響更新和插入的速度,因為它需要同樣更新每個索引文件。對于一個經常需要更新和插入的表格,就沒有必要為一個很少使用的where字句單獨建立索引了,對于比較小的表,排序的開銷不會很大,也沒有必要建立另外的索引。
以 上介紹的只是一些十分基本的東西,其實里面的學問也不少,單憑EXPLAIN我們是不能判定該方法是否就是最優化的,每個數據庫都有自己的一些優化器,雖 然可能還不太完善,但是它們都會在查詢時對比過哪種方式較快,在某些情況下,建立索引的話也未必會快,例如索引放在一個不連續的存儲空間時,這會增加讀磁 盤的負擔,因此,哪個是最優,應該通過實際的使用環境來檢驗。
在剛開始的時候,如果表不大,沒有必要作索引,我的意見是在需要的時候才作索引,也可用一些命令來優化表,例如MySQL可用"OPTIMIZE TABLE"。
綜上所述,在如何為數據庫建立恰當的索引方面,你應該有一些基本的概念了。

posted @ 2012-06-09 15:44 多彩人生 閱讀(453) | 評論 (0)編輯 收藏

數據庫的索引

索引

使用索引可快速訪問數據庫表中的特定信息。索引是對數據庫表中一列或多列的值進行排序的一種結構,例如 employee 表的姓(lname)列。如果要按姓查找特定職員,與必須搜索表中的所有行相比,索引會幫助您更快地獲得該信息。

索引提供指向存儲在表的指定列中的數據值的指針,然后根據您指定的排序順序對這些指針排序。數據庫使用索引的方式與您使用書籍中的索引的方式很相似:它搜索索引以找到特定值,然后順指針找到包含該值的行。

在數據庫關系圖中,您可以在選定表的“索引/鍵”屬性頁中創建、編輯或刪除每個索引類型。當保存索引所附加到的表,或保存該表所在的關系圖時,索引將保存在數據庫中。有關詳細信息,請參見創建索引。

注意;并非所有的數據庫都以相同的方式使用索引。有關更多信息,請參見數據庫服務器注意事項,或者查閱數據庫文檔。

作為通用規則,只有當經常查詢索引列中的數據時,才需要在表上創建索引。索引占用磁盤空間,并且降低添加、刪除和更新行的速度。在多數情況下,索引用于數據檢索的速度優勢大大超過它的。

索引列

可以基于數據庫表中的單列或多列創建索引。多列索引使您可以區分其中一列可能有相同值的行。

如果經常同時搜索兩列或多列或按兩列或多列排序時,索引也很有幫助。例如,如果經常在同一查詢中為姓和名兩列設置判據,那么在這兩列上創建多列索引將很有意義。

確定索引的有效性:

  • 檢查查詢的 WHERE 和 JOIN 子句。在任一子句中包括的每一列都是索引可以選擇的對象。
  • 對新索引進行試驗以檢查它對運行查詢性能的影響。
  • 考慮已在表上創建的索引數量。最好避免在單個表上有很多索引。
  • 檢查已在表上創建的索引的定義。最好避免包含共享列的重疊索引。
  • 檢查某列中唯一數據值的數量,并將該數量與表中的行數進行比較。比較的結果就是該列的可選擇性,這有助于確定該列是否適合建立索引,如果適合,確定索引的類型。
索引類型

根據數據庫的功能,可以在數據庫設計器中創建三種索引:唯一索引、主鍵索引和聚集索引。有關數據庫所支持的索引功能的詳細信息,請參見數據庫文檔。

提示:盡管唯一索引有助于定位信息,但為獲得最佳性能結果,建議改用主鍵或唯一約束。

唯一索引

唯一索引是不允許其中任何兩行具有相同索引值的索引。

當現有數據中存在重復的鍵值時,大多數數據庫不允許將新創建的唯一索引與表一起保存。數據庫還可能防止添加將在表中創建重復鍵值的新數據。例如,如果在 employee 表中職員的姓 (lname) 上創建了唯一索引,則任何兩個員工都不能同姓。

主鍵索引

數據庫表經常有一列或列組合,其值唯一標識表中的每一行。該列稱為表的主鍵。

在數據庫關系圖中為表定義主鍵將自動創建主鍵索引,主鍵索引是唯一索引的特定類型。該索引要求主鍵中的每個值都唯一。當在查詢中使用主鍵索引時,它還允許對數據的快速訪問。

聚集索引

在聚集索引中,表中行的物理順序與鍵值的邏輯(索引)順序相同。一個表只能包含一個聚集索引。

如果某索引不是聚集索引,則表中行的物理順序與鍵值的邏輯順序不匹配。與非聚集索引相比,聚集索引通常提供更快的數據訪問速度。

posted @ 2012-06-09 15:23 多彩人生 閱讀(361) | 評論 (0)編輯 收藏

PostgreSQL: 數組類型(array) 的使用

http://francs3.blog.163.com/blog/static/405767272011103105752290/
  PostgreSQL 支持數組類型,包括一維數組和多維數組,在某些應用場合數組的應用還是很需要的,
這里簡單介紹下一維數組的使用及有關數組函數和操作符的使用。
  
  
--定義數組
mydb=> create table test_array(id serial primary key, phone int8[]);
NOTICE:  CREATE TABLE will create implicit sequence "test_array_id_seq" for serial column "test_array.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "test_array_pkey" for table "test_array"
CREATE TABLE

mydb=> \d test_array
                           Table "mydb.test_array"
 Column |   Type   |                        Modifiers                       
--------+----------+---------------------------------------------------------
 id     | integer  | not null default nextval('test_array_id_seq'::regclass)
 phone  | bigint[] |
Indexes:
    "test_array_pkey" PRIMARY KEY, btree (id)


--數組元素插入有兩種方式
mydb=> insert into test_array(phone) values ('{1,2}');
INSERT 0 1
mydb=> insert into test_array(phone) values ('{2,3}');
INSERT 0 1

mydb=> insert into test_array(phone) values (array[3,4,5]);
INSERT 0 1

mydb=> select * From test_array;
 id |  phone 
----+---------
  1 | {1,2}
  2 | {2,3}
  3 | {3,4,5}
(3 rows)


--數組元素的引用
mydb=> select phone  from test_array where id=1;
 phone
-------
 {1,2}
(1 row)

mydb=> select phone[1],phone[2]  from test_array where id=1;
 phone | phone
-------+-------
     1 |     2
    
    
    
一 常見的數組操作(Array Operators)

PostgreSQL: 數組類型(array) 的使用 - francs - My DBA LIFE

 

--equal
mydb=>  select array[1,2]=array[1.1,2.1]::int[];
 ?column?
----------
 t
(1 row)

--not equal
mydb=> select array[1,2] <> array[1,2,3];
 ?column?
----------
 t
(1 row)


--less than
mydb=> select ARRAY[1,2,3] < ARRAY[1,2,4];
 ?column?
----------
 t
(1 row)


--greater than
mydb=> select ARRAY[1,4,3] > ARRAY[1,2,4];
 ?column?
----------
 t
(1 row)


--contains
mydb=> select ARRAY[1,4,3] @> ARRAY[3,1];
 ?column?
----------
 t
(1 row)


--is contained by
mydb=> select ARRAY[2,7] <@ ARRAY[1,7,4,2,6];
 ?column?
----------
 t
(1 row)


--overlap (have elements in common)
mydb=> select ARRAY[1,4,3] && ARRAY[2,1];
 ?column?
----------
 t
    

二 常見數組函數( Array Functions )
--將數據元素追加到數組
mydb=> select array_append(array[2,3,4],5);
 array_append
--------------
 {2,3,4,5}
(1 row)

--連接兩個數組
mydb=> select array_cat(array[1,2],array[3,4]);
 array_cat
-----------
 {1,2,3,4}
(1 row)

--獲得數組的維度
mydb=> select array_ndims(array[1,2,3]);
 array_ndims
-------------
           1
(1 row)

mydb=> select array_ndims(array[[1,2,3],[4,5,6]]);
 array_ndims
-------------
           2
(1 row)


--獲得數組的長度                                 ^
mydb=> select array_length(array[1,2,3],1);
 array_length
--------------
            3
(1 row)

mydb=> select array_length(array[[1,2],[2,3]],1);
 array_length
--------------
            2
(1 row)


三 intarray 模塊的數組函數
--獲取元素個數據總和
mydb=> select icount(array[1,2]);
 icount
--------
      2
(1 row)

mydb=> select icount(array[[1,2],[2,3]]);
 icount
--------
      4
(1 row)


--排序
mydb=> select sort_asc(array[4,8,7]);
 sort_asc
----------
 {4,7,8}
(1 row)

mydb=> select sort_desc(array[4,8,7]);
 sort_desc
-----------
 {8,7,4}
(1 row)

mydb=> select sort_desc(array[[4,8,7],[8,9,7]]);
     sort_desc    
-------------------
 {{9,8,8},{7,7,4}}
(1 row)


四 intarray 模塊的數組操作符

PostgreSQL: 數組類型(array) 的使用 - francs - My DBA LIFE

 

--表數據
mydb=> select * from test_array;
 id |  phone 
----+---------
  1 | {1,2}
  2 | {2,3}
  3 | {3,4,5}
  4 | {4,5,6}
  5 | {4,5,7}
(5 rows)


--查找包括相同元素的記錄
mydb=> select id ,phone from test_array where phone && array[1,2]::int8[];
 id | phone
----+-------
  1 | {1,2}
  2 | {2,3}
(2 rows)


--查找數組元素的交集
mydb=> select array[1,2,3] & array[3,4,5];
 ?column?
----------
 {3}
(1 row)


五 索引的使用
  
          數組支持創建 GiST 和 GIN 類型索引,這兩類索引的選擇要根據場合,簡單的說, GIN 類型索引在查詢上要比
  GiST 類型索引快,但在 update 的時候要慢些,所以 GIN 類型索引適合表數據不太變化的場合,而 GiST 索引適用
  于表數據經常需要 UPDATE 的場景。

posted @ 2012-06-08 16:04 多彩人生 閱讀(1482) | 評論 (0)編輯 收藏

網絡傳輸字序

大多數情況下服務器的環境是固定的,所以一般服務就按自己的字序來傳輸,而在client作轉換,轉換成與server一致的就可以了,
如果,你的服務器環境多樣,那就要考慮轉換成網絡字序,便于移植

posted @ 2012-06-02 15:31 多彩人生 閱讀(129) | 評論 (0)編輯 收藏

linux 斷開某個用戶的終端連接

斷開某個用戶的連接
who 查看用戶連接

斷開遠程用戶
fuser -k /dev/pts/x

x為who下看到的這個用戶的pts序號

斷開本地用戶

fuser -k /dev/ttyx

x為who查看到的tty序號

posted @ 2012-05-31 20:14 多彩人生 閱讀(905) | 評論 (0)編輯 收藏

error while loading shared libraries的解決方法

 行程式時,如此遇到像下列這種錯誤:
./tests: error while loading shared libraries: xxx.so.0:cannot open shared object file: No such file or directory
那就表示系統不知道xxx.so 放在哪個目錄下。
這個時候就要在/etc/ld.so.conf中加入xxx.so所在的目錄。
 一般而言,有很多so檔會在/usr/local/lib這個目錄下,所以在/etc/ld.so.conf中加入/usr/local/lib這一行,可以解決此問題。
將 /etc/ld.so.conf存檔後,還要執行「/sbin/ldconfig –v」來更新一下才會生效。

posted @ 2012-05-30 19:36 多彩人生 閱讀(339) | 評論 (0)編輯 收藏

僅列出標題
共25頁: First 12 13 14 15 16 17 18 19 20 Last 

導航

統計

常用鏈接

留言簿(3)

隨筆分類

隨筆檔案

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美日韩国产综合| 在线成人av网站| 一区二区三区视频观看| 亚洲精品一区二| 一区二区日韩免费看| 亚洲一区二区三区免费视频| 性18欧美另类| 农夫在线精品视频免费观看| 欧美区日韩区| 国产日韩欧美综合精品| 伊人成人开心激情综合网| 亚洲精品在线免费观看视频| 校园激情久久| 欧美成人免费网站| 99在线精品免费视频九九视| 欧美在线电影| 欧美激情片在线观看| 国产精品久久久久久久午夜 | 狠狠色综合色区| 亚洲人线精品午夜| 亚洲一区二区三区在线播放| 久久久av网站| 91久久精品美女| 亚洲五月婷婷| 欧美电影打屁股sp| 国产偷国产偷亚洲高清97cao | 欧美一级淫片播放口| 男人插女人欧美| 国产精品99久久久久久白浆小说 | 久久久噜噜噜久久狠狠50岁| 欧美久久九九| 在线国产精品一区| 亚洲欧美日韩一区在线观看| 欧美激情综合| 久久九九国产精品| 国产欧美精品在线| 亚洲深爱激情| 最新中文字幕一区二区三区| 久久精品九九| 国产麻豆精品久久一二三| 宅男精品导航| 亚洲视频欧美视频| 亚洲日本aⅴ片在线观看香蕉| 亚洲欧美一区二区三区极速播放 | 国产欧美精品在线| 亚洲电影在线看| 亚洲午夜免费福利视频| 亚洲国产天堂久久综合| 久久爱www久久做| 国产精品午夜在线| 亚洲男人的天堂在线aⅴ视频| 亚洲成色999久久网站| 久久免费高清视频| 伊人成综合网伊人222| 久久久久女教师免费一区| 亚洲自拍偷拍一区| 国产精品美女主播| 亚洲欧美激情四射在线日| 亚洲精品久久久久| 欧美国产日韩精品| 99国内精品久久| 亚洲精品一区久久久久久| 欧美日韩第一区| 亚洲深夜福利网站| 亚洲午夜免费福利视频| 国产精品理论片| 久久se精品一区二区| 欧美一级网站| 激情一区二区| 欧美高清一区| 欧美三级电影一区| 久久国产精品一区二区三区| 久久国产精品免费一区| 在线欧美日韩精品| 亚洲裸体俱乐部裸体舞表演av| 欧美日韩亚洲一区二| 亚洲特级毛片| 久久精品国产亚洲高清剧情介绍| 激情综合网激情| 亚洲国产视频一区| 国产精品捆绑调教| 蜜桃久久精品乱码一区二区| 欧美电影资源| 亚洲欧美日韩一区二区三区在线观看| 亚洲第一在线| 亚洲高清视频在线| 欧美日韩午夜剧场| 久久精品国产久精国产一老狼 | 欧美日韩综合在线| 亚洲精品在线免费观看视频| av72成人在线| 91久久久国产精品| 亚洲男人第一网站| 欧美天堂在线观看| 久久本道综合色狠狠五月| 免费观看在线综合| 亚洲日韩视频| 久久久水蜜桃| 亚洲视频精选在线| 久久精品在线| 18成人免费观看视频| 亚洲免费一级电影| 午夜国产精品视频免费体验区| 免费日韩av| 中文在线一区| 亚洲久色影视| 99热免费精品| 免费高清在线视频一区·| 久久成人免费网| 日韩午夜激情av| 欧美一区二区在线视频| 亚洲欧美久久久| 欧美国产激情| 一二三区精品福利视频| 亚洲一区二区黄色| 99亚洲伊人久久精品影院红桃| 欧美一二三视频| 欧美日韩国产一级| 亚洲国产成人精品久久| 亚洲男人的天堂在线观看| 一本色道久久综合亚洲精品不| 久久九九免费视频| 欧美综合二区| 国产精品久久久久久超碰| 亚洲激情在线观看| 亚洲成人原创| 久久国产88| 欧美影院精品一区| 国产噜噜噜噜噜久久久久久久久| 亚洲另类视频| 99这里有精品| 欧美日韩一区二区免费视频| 亚洲人成艺术| 99国产一区| 欧美少妇一区二区| 日韩午夜剧场| 亚洲手机成人高清视频| 欧美日韩国产影片| 一区二区激情视频| 亚洲一区观看| 国产欧美日韩综合精品二区| 亚洲淫片在线视频| 亚洲日本无吗高清不卡| 久久久精品一区二区三区| 亚洲免费网址| 久久在精品线影院精品国产| 亚洲第一精品影视| 猛干欧美女孩| 亚洲美女啪啪| 一区二区高清在线| 欧美成年人网| 欧美日韩国产亚洲一区| 久久久噜噜噜久噜久久| 一区二区三区免费网站| 久久人人爽国产| 欧美成人四级电影| 亚洲美女毛片| 国产精品久久久久久福利一牛影视| 一本高清dvd不卡在线观看| 亚洲女爱视频在线| 国产一区二区精品在线观看| 久久久久久夜| 亚洲乱码国产乱码精品精| 午夜精品视频在线观看一区二区| 国产亚洲美州欧州综合国| 久久久久一区| 一区二区三区精密机械公司| 久久人人97超碰精品888| 亚洲精品影院在线观看| 国产精品国产亚洲精品看不卡15| 性色av一区二区三区| 亚洲第一页在线| 亚洲一区成人| 在线观看日韩国产| 欧美日韩免费在线视频| 新狼窝色av性久久久久久| 亚洲第一区在线| 欧美一级大片在线观看| 亚洲福利在线看| 国产精品男人爽免费视频1| 久久精品一区二区三区四区| 亚洲精选大片| 免费观看30秒视频久久| 午夜精品久久久久久久白皮肤| 激情av一区| 国产精品毛片在线| 欧美国产日韩在线| 久久国产天堂福利天堂| 亚洲午夜性刺激影院| 亚洲国产精彩中文乱码av在线播放| 亚洲欧美不卡| 日韩一区二区精品在线观看| 狠狠色香婷婷久久亚洲精品| 国产精品盗摄久久久| 欧美sm重口味系列视频在线观看| 欧美一区二区在线免费播放| 亚洲视频一区二区免费在线观看| 亚洲国产女人aaa毛片在线| 久久性天堂网| 欧美一站二站|