• <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>

            colorful

            zc qq:1337220912

             

            shared_from_this 幾個值得注意的地方

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

            如下代碼是錯誤的:
            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. };
            復(fù)制代碼
            原 因很簡單,在D的構(gòu)造函數(shù)中雖然可以保證enable_shared_from_this<D>的構(gòu)造函數(shù)已經(jīng)被調(diào)用,但正如前面所 說,weak_ptr還沒有設(shè)置。

            如下代碼也是錯誤的:
            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. }
            復(fù)制代碼
            錯 誤原因同上。

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

            結(jié)論是,不要在構(gòu)造函數(shù)中使用shared_from_this;其次,如果要使用shared_ptr,則應(yīng)該 在所有地方均使用,不能使用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. }
            復(fù)制代碼
            注 意上面代碼中,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>的構(gòu)造函數(shù)僅會設(shè)置2個基類中的一個的weak_ptr。在上面的例子中,僅設(shè)置 enable_shared_from_this<A>的。如果修改B的定義為:

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

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

            那么enable_shared_from_this以及shared_ptr為何要如此實現(xiàn)呢?又為什么會有如此怪異的結(jié)果呢?

            首先考察shared_ptr的構(gòu)造函數(shù):
            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. }
            復(fù)制代碼
            注 意這個sp_enable_shared_from_this是一個模板函數(shù),而且僅調(diào)用了一次,所以不可能2個 enable_shared_from_this基類的weak_ptr都被賦值。但問題在于,在調(diào)換了B的定義之后結(jié)果居然是不一樣的。這里有一個很隱 秘的編譯器BUG。按道理來說,編譯器在編譯這段代碼時,應(yīng)該注意到無法真正決斷該怎么實例化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. };
            復(fù)制代碼
            注 意到這里B并沒有直接繼承enable_shared_from_this,而是使用dynamic_pointer_cast進行了類型轉(zhuǎn)換。

            關(guān)于為什么enable_shared_from_this是這樣實現(xiàn)的,可以參看作者原文:

            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必須具有虛函數(shù),那么最簡單的做法當(dāng)然是令其析構(gòu)函 數(shù)為虛函數(shù)(通常一個class如果希望被繼承,析構(gòu)函數(shù)就應(yīng)該為虛函數(shù))

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

            enable_shared_from_this(轉(zhuǎn)載)

            在 C++ 中需要自己來處理內(nèi)存,稍微處理不當(dāng),就會存在非常郁悶的內(nèi)存泄漏問題

             

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

             

            除了標(biāo)準(zhǔn)庫中的 auto_ptr 之外

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

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

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

             

            在下面的代碼中:

             

            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() 成員函數(shù),則會輸出 a 和 b 的 use_count() 都為 1 ,然后調(diào)用 2 次類型 Ansible 的析構(gòu)函數(shù),若添加了該成員函數(shù),在 a 和 b 的 use_count() 輸出為 2 ,只是調(diào)用一次 Ansible 的析構(gòu)函數(shù)。原因是 enable_shared_from_this 里面在 shared_ptr<T> 的時候構(gòu)造了一個 weak_ptr 類,而 weak_ptr 只是監(jiān)視,不增加引用計數(shù)

             

            (下面是轉(zhuǎn)載: 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 的構(gòu)造函數(shù)中雖然可以保證 enable_shared_from_this<D> 的構(gòu)造函數(shù)已經(jīng)被調(diào)用,但正如前面所說, weak_ptr 還沒有設(shè)置。

             

            如下代碼也是錯誤的:

             

            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) 實際上執(zhí)行了 3 個動作:首先調(diào)用 enable_shared_from_this<D> 的構(gòu)造函數(shù);其次調(diào)用 D 的構(gòu)造函數(shù);最后調(diào)用 shared_ptr<D> 的構(gòu)造函數(shù)。是第 3 個動作設(shè)置了 enable_shared_from_this<D> 的 weak_ptr ,而不是第 1 個動作。這個地方是很違背 c++ 常理和邏輯的,必須小心。

             

            結(jié)論是,不要在構(gòu)造函數(shù)中使用 shared_from_this ;其次,如果要使用 shared_ptr ,則應(yīng)該在所有地方均使用,不能使用 D d 這種方式,也決不要傳遞裸指針。


            另解:::::
            struct X

            {

                     boost::shared_ptr<X> getX()

            {

                     boost::shared_ptr<X> r ;//????如何實現(xiàn)

                     return r;

            }

            };

             

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

            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 多彩人生 閱讀(479) | 評論 (0)編輯 收藏

            stl string常用函數(shù)

            string類的構(gòu)造函數(shù):
            string(const char *s); //用c字符串s初始化
            string(int n,char c); //用n個字符c初始化
            此外,string類還支持默認構(gòu)造函數(shù)和復(fù)制構(gòu)造函數(shù),如string s1;string s2="hello";都是正確的寫法。當(dāng)構(gòu)造的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()均返回當(dāng)前字符串中第n個字符的位置,但at函數(shù)提供范圍檢查,當(dāng)越界時會拋出out_of_range異常,下標(biāo)運算符[]不提供檢查訪問。
            const char *data()const;//返回一個非null終止的c字符數(shù)組
            const char *c_str()const;//返回一個以null終止的c字符串
            int copy(char *s, int n, int pos = 0) const;//把當(dāng)前串中以pos開始的n個字符拷貝到以s為起始位置的字符數(shù)組中,返回實際拷貝的數(shù)目

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

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

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

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

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

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


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

            string類的查找函數(shù):

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

            int rfind(char c, int pos = npos) const;//從pos開始從后向前查找字符c在當(dāng)前串中的位置
            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個字符組成的字符串在當(dāng)前串中的位置,成功返回所在位置,失敗時返回string::npos的值

            int find_first_of(char c, int pos = 0) const;//從pos開始查找字符c第一次出現(xiàn)的位置
            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開始查找當(dāng)前串中第一個在s的前n個字符組成的數(shù)組里的字符的位置。查找失敗返回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;
            //從當(dāng)前串中查找第一個不在串s中的字符出現(xiàn)的位置,失敗返回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類的替換函數(shù):

            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類的插入函數(shù):

            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個函數(shù)在p0位置插入字符串s中pos開始的前n個字符
            string &insert(int p0, int n, char c);//此函數(shù)在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類的刪除函數(shù)

            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不允許改變迭代的內(nèi)容。常用迭代器函數(shù)有:
            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用于從后向前的迭代訪問,通過設(shè)置迭代器string::reverse_iterator,string::const_reverse_iterator實現(xiàn)

            字符串流處理:

            通過定義ostringstream和istringstream變量實現(xiàn),
            <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 多彩人生 閱讀(238) | 評論 (0)編輯 收藏

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

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

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

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

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

            2.文本文件與二進制文件的區(qū)別:

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

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

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

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

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

            為數(shù)據(jù)庫建立索引

            最普通的情況,是為出現(xiàn)在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;
            最直接的應(yīng)對之道,是為category_id建立一個簡單的索引:
             CREATE INDEX mytable_categoryid
             ON mytable (category_id);
            OK.如果你有不止一個選擇條件呢?例如:
             SELECT * FROM mytable WHERE category_id=1 AND user_id=2;
            你的第一反應(yīng)可能是,再給user_id建立一個索引。不好,這不是一個最佳的方法。你可以建立多重的索引。
            CREATE INDEX mytable_categoryid_userid ON mytable (category_id,user_id);
            注意到我在命名時的習(xí)慣了嗎?我使用"表名_字段1名_字段2名"的方式。你很快就會知道我為什么這樣做了。
            現(xiàn)在你已經(jīng)為適當(dāng)?shù)淖侄谓⒘怂饕贿^,還是有點不放心吧,你可能會問,數(shù)據(jù)庫會真正用到這些索引嗎?測試一下就OK,對于大多數(shù)的數(shù)據(jù)庫來說,這是很容易的,只要使用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的數(shù)據(jù),可以看到該數(shù)據(jù)庫在查詢的時候使用了一個索引(一個好開始),而且它使用的是我創(chuàng)建的第二個索引。看到我上面命名的好處了吧,你馬上知道它使用適當(dāng)?shù)乃饕恕?/p>

            接著,來個稍微復(fù)雜一點的,如果有個ORDER BY字句呢?不管你信不信,大多數(shù)的數(shù)據(jù)庫在使用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的輸出,數(shù)據(jù)庫多做了一個我們沒有要求的排序,這下知道性能如何受損了吧,看來我們對于數(shù)據(jù)庫的自身運作是有點過于樂觀了,那么,給數(shù)據(jù)庫多一點提示吧。
            為 了跳過排序這一步,我們并不需要其它另外的索引,只要將查詢語句稍微改一下。這里用的是postgres,我們將給該數(shù)據(jù)庫一個額外的提示--在 ORDER BY語句中,加入where語句中的字段。這只是一個技術(shù)上的處理,并不是必須的,因為實際上在另外兩個字段上,并不會有任何的排序操作,不過如果加 入,postgres將會知道哪些是它應(yīng)該做的。
             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
            現(xiàn)在使用我們料想的索引了,而且它還挺聰明,知道可以從索引后面開始讀,從而避免了任何的排序。
            以 上說得細了一點,不過如果你的數(shù)據(jù)庫非常巨大,并且每日的頁面請求達上百萬算,我想你會獲益良多的。不過,如果你要做更為復(fù)雜的查詢呢,例如將多張表結(jié)合 起來查詢,特別是where限制字句中的字段是來自不止一個表格時,應(yīng)該怎樣處理呢?我通常都盡量避免這種做法,因為這樣數(shù)據(jù)庫要將各個表中的東西都結(jié)合 起來,然后再排除那些不合適的行,搞不好開銷會很大。
            如果不能避免,你應(yīng)該查看每張要結(jié)合起來的表,并且使用以上的策略來建立索引,然后再用EXPLAIN命令驗證一下是否使用了你料想中的索引。如果是的話,就OK。不是的話,你可能要建立臨時的表來將他們結(jié)合在一起,并且使用適當(dāng)?shù)乃饕?
            要注意的是,建立太多的索引將會影響更新和插入的速度,因為它需要同樣更新每個索引文件。對于一個經(jīng)常需要更新和插入的表格,就沒有必要為一個很少使用的where字句單獨建立索引了,對于比較小的表,排序的開銷不會很大,也沒有必要建立另外的索引。
            以 上介紹的只是一些十分基本的東西,其實里面的學(xué)問也不少,單憑EXPLAIN我們是不能判定該方法是否就是最優(yōu)化的,每個數(shù)據(jù)庫都有自己的一些優(yōu)化器,雖 然可能還不太完善,但是它們都會在查詢時對比過哪種方式較快,在某些情況下,建立索引的話也未必會快,例如索引放在一個不連續(xù)的存儲空間時,這會增加讀磁 盤的負擔(dān),因此,哪個是最優(yōu),應(yīng)該通過實際的使用環(huán)境來檢驗。
            在剛開始的時候,如果表不大,沒有必要作索引,我的意見是在需要的時候才作索引,也可用一些命令來優(yōu)化表,例如MySQL可用"OPTIMIZE TABLE"。
            綜上所述,在如何為數(shù)據(jù)庫建立恰當(dāng)?shù)乃饕矫妫銘?yīng)該有一些基本的概念了。

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

            數(shù)據(jù)庫的索引

            索引

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

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

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

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

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

            索引列

            可以基于數(shù)據(jù)庫表中的單列或多列創(chuàng)建索引。多列索引使您可以區(qū)分其中一列可能有相同值的行。

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

            確定索引的有效性:

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

            根據(jù)數(shù)據(jù)庫的功能,可以在數(shù)據(jù)庫設(shè)計器中創(chuàng)建三種索引:唯一索引、主鍵索引和聚集索引。有關(guān)數(shù)據(jù)庫所支持的索引功能的詳細信息,請參見數(shù)據(jù)庫文檔。

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

            唯一索引

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

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

            主鍵索引

            數(shù)據(jù)庫表經(jīng)常有一列或列組合,其值唯一標(biāo)識表中的每一行。該列稱為表的主鍵。

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

            聚集索引

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

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

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

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

            http://francs3.blog.163.com/blog/static/405767272011103105752290/
              PostgreSQL 支持?jǐn)?shù)組類型,包括一維數(shù)組和多維數(shù)組,在某些應(yīng)用場合數(shù)組的應(yīng)用還是很需要的,
            這里簡單介紹下一維數(shù)組的使用及有關(guān)數(shù)組函數(shù)和操作符的使用。
              
              
            --定義數(shù)組
            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)


            --數(shù)組元素插入有兩種方式
            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)


            --數(shù)組元素的引用
            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
                
                
                
            一 常見的數(shù)組操作(Array Operators)

            PostgreSQL: 數(shù)組類型(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
                

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

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

            --獲得數(shù)組的維度
            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)


            --獲得數(shù)組的長度                                 ^
            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 模塊的數(shù)組函數(shù)
            --獲取元素個數(shù)據(jù)總和
            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 模塊的數(shù)組操作符

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

             

            --表數(shù)據(jù)
            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)


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


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

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

            網(wǎng)絡(luò)傳輸字序

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

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

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

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

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

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

            斷開本地用戶

            fuser -k /dev/ttyx

            x為who查看到的tty序號

            posted @ 2012-05-31 20:14 多彩人生 閱讀(897) | 評論 (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
            那就表示系統(tǒng)不知道xxx.so 放在哪個目錄下。
            這個時候就要在/etc/ld.so.conf中加入xxx.so所在的目錄。
             一般而言,有很多so檔會在/usr/local/lib這個目錄下,所以在/etc/ld.so.conf中加入/usr/local/lib這一行,可以解決此問題。
            將 /etc/ld.so.conf存檔後,還要執(zhí)行「/sbin/ldconfig –v」來更新一下才會生效。

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

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

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲精品美女久久777777| 狠狠综合久久综合88亚洲| 狠狠色综合网站久久久久久久 | 亚洲综合日韩久久成人AV| 久久99精品久久久久婷婷| 久久国产精品免费一区| 久久久久亚洲av无码专区| 精品久久久无码中文字幕| 久久精品国产色蜜蜜麻豆| 久久99久久99小草精品免视看 | 久久r热这里有精品视频| 青草久久久国产线免观| 精品国产91久久久久久久| 99久久夜色精品国产网站| 色偷偷888欧美精品久久久| 亚洲精品无码久久久久sm| 久久成人精品| 天天综合久久久网| 国产精品岛国久久久久| 国产精品99久久久精品无码| 欧美精品丝袜久久久中文字幕| 久久中文字幕一区二区| 亚洲精品tv久久久久久久久 | 久久国产成人| 国产精品久久久久久一区二区三区| 漂亮人妻被中出中文字幕久久 | 久久996热精品xxxx| 久久免费线看线看| www.久久热.com| 波多野结衣中文字幕久久| 久久天天躁狠狠躁夜夜avapp| 亚洲精品乱码久久久久久蜜桃不卡 | 亚洲综合伊人久久综合| 狠狠色狠狠色综合久久| 久久久久久午夜精品| 色天使久久综合网天天| 亚洲AV无码久久精品蜜桃| 久久综合精品国产二区无码| 久久偷看各类wc女厕嘘嘘| 72种姿势欧美久久久久大黄蕉| 久久国产欧美日韩精品|