国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
為什么需要auto

么需要auto_ptr_ref

為什么需要auto_ptr_ref

這幾天開始拜讀侯捷先生和孟巖先生的譯作《C++標(biāo)準(zhǔn)程序庫:自修教程與參考手冊》 。兩位先生確實(shí)譯功上乘,讀得很順。但是讀到P55頁關(guān)于auto_ptr_ref的討論,卻百思不得其解:為什么需要引入auto_ptr_ref這個(gè)輔助類呢?

從書中描述來看,仿佛與拷貝構(gòu)造函數(shù)右值 、類型轉(zhuǎn)換 有關(guān)。于是,結(jié)合auto_ptr的源代碼,google之、baidu之,找了一推資料,終于初步 搞清該問題。

auto_ptr的擁有權(quán)

C++常見的智能指針有std::auto_ptr、boost::shared_ptr、boost::scoped_ptr、boost::shared_array、boost::scoped_array等。auto_ptr只是其中一種而已。但是,為什么auto_ptr才有auto_ptr_ref ,而boost::shared_ptr卻沒有shared_ptr_ref呢?

 

答案與auto_ptr的特性有關(guān)。auto_ptr強(qiáng)調(diào)對資源的擁有權(quán) (ownership)。也就是說,auto_ptr是"它所指對象"的擁有者。而一個(gè)對象只能屬于一個(gè)擁有者,嚴(yán)禁一物二主,否則就是重婚罪,意料外的災(zāi)難將隨之而來。

 

為了保證auto_ptr的擁有權(quán)唯一,auto_ptr的拷貝構(gòu)造函數(shù)和賦值操作符做了這樣一件事情:移除另一個(gè)auto_ptr的擁有權(quán) 。為了說明擁有權(quán)的轉(zhuǎn)移 ,請看下面的代碼示例:

Cpp代碼 

  1. #include <iostream>   
  2. #include <memory>   
  3. using namespace std;   
  4.   
  5. int main(int argc, char **argv){   
  6.     auto_ptr<int> ptr1(new int(1));   
  7.     auto_ptr<int> ptr2(ptr1); //ptr1的擁有權(quán)被轉(zhuǎn)移到ptr2   
  8.   
  9.     auto_ptr<int> ptr3(NULL);   
  10.     ptr3 = ptr2;                //ptr2的擁有權(quán)被轉(zhuǎn)移到ptr3   
  11.   
  12.     cout<<ptr1.get()<<endl;     //結(jié)果為0   
  13.     cout<<ptr2.get()<<endl;     //結(jié)果為0   
  14.     cout<<*ptr3<<endl;          //結(jié)果為1  

#include <iostream>

#include <memory>

using namespace std;

 

int main(int argc, char **argv){

  auto_ptr<int> ptr1(new int(1));

  auto_ptr<int> ptr2(ptr1);  //ptr1的擁有權(quán)被轉(zhuǎn)移到ptr2

 

  auto_ptr<int> ptr3(NULL);

  ptr3 = ptr2;       //ptr2的擁有權(quán)被轉(zhuǎn)移到ptr3

 

  cout<<ptr1.get()<<endl;   //結(jié)果為0

  cout<<ptr2.get()<<endl;   //結(jié)果為0

  cout<<*ptr3<<endl;        //結(jié)果為1

 

auto_ptr的拷貝構(gòu)造函數(shù)與賦值操作符  

由于需要實(shí)現(xiàn)擁有權(quán)的轉(zhuǎn)移,auto_ptr的拷貝構(gòu)造函數(shù)和賦值操作符,與一般類的做法不太相同。我們可以看看MinGW5.1.6實(shí)現(xiàn)的auto_ptr源代碼:

Cpp代碼 

  1.  /**  
  2.  *  @brief  An %auto_ptr can be constructed from another %auto_ptr.  
  3.  *  @param  a  Another %auto_ptr of the same type.  
  4.  *  
  5.  *  This object now @e owns the object previously owned by @a a,  
  6.  *  which has given up ownsership.  
  7.  */  
  8. auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) {}   
  9.   
  10. /**  
  11.  *  @brief  %auto_ptr assignment operator.  
  12.  *  @param  a  Another %auto_ptr of the same type.  
  13.  *  
  14.  *  This object now @e owns the object previously owned by @a a,  
  15.  *  which has given up ownsership.  The object that this one @e  
  16.  *  used to own and track has been deleted.  
  17.  */  
  18. auto_ptr&   
  19. operator=(auto_ptr& __a) throw () {   
  20.     reset(__a.release());   
  21.     return *this;   
  22. }  

 /**

 *  @brief  An %auto_ptr can be constructed from another %auto_ptr.

 *  @param  a  Another %auto_ptr of the same type.

 *

 *  This object now @e owns the object previously owned by @a a,

 *  which has given up ownsership.

 */

auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) {}

 

/**

 *  @brief  %auto_ptr assignment operator.

 *  @param  a  Another %auto_ptr of the same type.

 *

 *  This object now @e owns the object previously owned by @a a,

 *  which has given up ownsership.  The object that this one @e

 *  used to own and track has been deleted.

 */

auto_ptr&

operator=(auto_ptr& __a) throw () {

reset(__a.release());

return *this;

}

 

    可以看到,auto_ptr的拷貝構(gòu)造函數(shù)、賦值操作符,它們的參數(shù)都是auto_ptr& ,而不是auto_ptr const & 。

    一般來說,類的拷貝構(gòu)造函數(shù)和賦值操作符的參數(shù)都是const &。但是auto_ptr的做法也是合理的:確保擁有權(quán)能夠轉(zhuǎn)移 。

    如果auto_ptr的拷貝構(gòu)造函數(shù)和賦值操作符的參數(shù)是auto_ptr const & ,那么實(shí)參的擁有權(quán)將不能轉(zhuǎn)移。因?yàn)檗D(zhuǎn)移擁有權(quán)需要修改auto_ptr的成員變量,而實(shí)參確是一個(gè)const對象,不允許修改。

 

右值與const &

假設(shè)我們想寫出下面的代碼:

Cpp代碼 

  1. #include <iostream>   
  2. #include <memory>   
  3. using namespace std;   
  4.   
  5. int main(int argc, char **argv) {   
  6.     auto_ptr<int> ptr1(auto_ptr<int>(new int(1)));  //使用臨時(shí)對象進(jìn)行拷貝構(gòu)造   
  7.     auto_ptr<int> ptr2(NULL);   
  8.     ptr2 = (auto_ptr<int>(new int(2)));           //使用臨時(shí)對象進(jìn)行賦值   
  9. }  

#include <iostream>

#include <memory>

using namespace std;

 

int main(int argc, char **argv) {

auto_ptr<int> ptr1(auto_ptr<int>(new int(1)));  //使用臨時(shí)對象進(jìn)行拷貝構(gòu)造

auto_ptr<int> ptr2(NULL);

ptr2 = (auto_ptr<int>(new int(2)));     //使用臨時(shí)對象進(jìn)行賦值

}

 

    假設(shè)沒有定義auto_ptr_ref類及相關(guān)的函數(shù),那么這段代碼將不能通過編譯。主要的原因是,拷貝構(gòu)造函數(shù)及賦值操作符的參數(shù):auto_ptr<int>(new int(1))和 auto_ptr<int>(new int(2)) 都是臨時(shí)對象 。臨時(shí)對象屬于典型的右值 ,而非const &是不能指向右值的(就是說給引用賦值) (參見More Effective C++ ,Item 19)。auto_ptr的拷貝構(gòu)造函數(shù)及賦值操作符的參數(shù)類型恰恰是auto_ptr&,明顯 非const &。

 左值和右值

左值可以出現(xiàn)在賦值語句的左邊或右邊

右值只能出現(xiàn)在賦值語句的右邊。

例如 x*y是個(gè)右值,編譯表達(dá)式x*y=10;則出現(xiàn)錯(cuò)誤

const引用不能綁定右值

2011-9-3 16:44

提問者: 古刃霜?jiǎng)?/a>| 瀏覽次數(shù):78次

為什么 const &a=40是對的,而&a=40是錯(cuò)的,其中具體的原理是怎樣的?
&a是對a解引用了,是a的地址,當(dāng)然不能把40復(fù)給他
而const必須在聲明時(shí)初始化,也就是const &a=40是初始化而不是把40給賦值,所以編譯能通過

 

    同理,下面的兩段代碼,也不會(huì)通過編譯:

Cpp代碼 

  1. #include <iostream>   
  2. #include <memory>   
  3. using namespace std;   
  4. auto_ptr<int> f();   
  5. int main(int argc, char **argv) {   
  6.     auto_ptr<int> ptr3(f());  //使用臨時(shí)對象進(jìn)行拷貝構(gòu)造   
  7.     auto_ptr<int> ptr4(NULL);   
  8.     ptr4 = f();               //使用臨時(shí)對象進(jìn)行賦值   
  9. }  

#include <iostream>

#include <memory>

using namespace std;

auto_ptr<int> f();

int main(int argc, char **argv) {

auto_ptr<int> ptr3(f());  //使用臨時(shí)對象進(jìn)行拷貝構(gòu)造

auto_ptr<int> ptr4(NULL);

ptr4 = f();       //使用臨時(shí)對象進(jìn)行賦值

}

Cpp代碼 

  1. #include <iostream>   
  2. #include <memory>   
  3. using namespace std;   
  4. auto_ptr<int> f(){   
  5.     return auto_ptr<int>(new int(3));  //這里其實(shí)也使用臨時(shí)對象進(jìn)行拷貝構(gòu)造   
  6. }  

#include <iostream>

#include <memory>

using namespace std;

auto_ptr<int> f(){

return auto_ptr<int>(new int(3));  //這里其實(shí)也使用臨時(shí)對象進(jìn)行拷貝構(gòu)造

}

 

    普通類不會(huì)遇到這個(gè)問題,是因?yàn)樗麄兊目截悩?gòu)造函數(shù)及賦值操作符(不管是用戶定義還是編譯器生成的版本),參數(shù)都是const &。

 

auto_ptr_ref之目的

傳說當(dāng)年C++標(biāo)準(zhǔn)委員會(huì)的好多國家,因?yàn)檫@個(gè)問題都想把a(bǔ)uto_ptr從標(biāo)準(zhǔn)庫中剔除。好在Bill Gibbons和Greg Colvin創(chuàng)造性地提出了auto_ptr_ref,解決了這一問題,世界清靜了。

 

auto_ptr_ref之原理

    很顯然,下面的構(gòu)造函數(shù),是可以接收auto_ptr臨時(shí)對象的。

Cpp代碼 

  1. auto_ptr(auto_ptr __a) throw() : _M_ptr(__a.release()) { }  

auto_ptr(auto_ptr __a) throw() : _M_ptr(__a.release()) { }

 

    但另一個(gè)問題也很顯然:上述構(gòu)造函數(shù)不能通過編譯。如果能通過編譯,就會(huì)陷入循環(huán)調(diào)用。我們稍作修改:

Cpp代碼 

  1. auto_ptr(auto_ptr_ref<element_type> __ref) throw()  //element_type就是auto_ptr的模板參數(shù)。   
  2.       : _M_ptr(__ref._M_ptr) { }   

auto_ptr(auto_ptr_ref<element_type> __ref) throw()  //element_type就是auto_ptr的模板參數(shù)。

      : _M_ptr(__ref._M_ptr) { }

 

    該版本的構(gòu)造函數(shù),可以接收auto_ptr_ref的臨時(shí)對象。如果auto_ptr可以隱式轉(zhuǎn)換到auto_ptr_ref,那么我們就能夠用auto_ptr臨時(shí)對象來調(diào)用該構(gòu)造函數(shù)。這個(gè)隱式轉(zhuǎn)換不難實(shí)現(xiàn):

Cpp代碼 

  1. template<typename _Tp1>   
  2.         operator auto_ptr_ref<_Tp1>() throw()   
  3.         { return auto_ptr_ref<_Tp1>(this->release()); }  

template<typename _Tp1>

        operator auto_ptr_ref<_Tp1>() throw()

        { return auto_ptr_ref<_Tp1>(this->release()); }

 

    至此,我們可以寫出下面的代碼,并可以通過編譯:

Cpp代碼 

  1. #include <iostream>   
  2. #include <memory>   
  3. using namespace std;   
  4.   
  5. int main(int argc, char **argv) {   
  6.     auto_ptr<int> ptr1(auto_ptr<int>(new int(1)));  //調(diào)用auto_ptr_ref版本的構(gòu)造函數(shù)   
  7. }  

#include <iostream>

#include <memory>

using namespace std;

 

int main(int argc, char **argv) {

auto_ptr<int> ptr1(auto_ptr<int>(new int(1)));  //調(diào)用auto_ptr_ref版本的構(gòu)造函數(shù)

}

 

   同理,如果我們再提供下面的函數(shù):

Cpp代碼 

  1. auto_ptr&   
  2.      operator=(auto_ptr_ref<element_type> __ref) throw()   
  3.      {   
  4. if (__ref._M_ptr != this->get())   
  5.   {   
  6.     delete _M_ptr;   
  7.     _M_ptr = __ref._M_ptr;   
  8.   }   
  9. return *this;   
  10.      }  

 auto_ptr&

      operator=(auto_ptr_ref<element_type> __ref) throw()

      {

if (__ref._M_ptr != this->get())

  {

    delete _M_ptr;

    _M_ptr = __ref._M_ptr;

  }

return *this;

      }

 

    那么,下面的代碼也可以通過編譯:

Cpp代碼 

  1. #include <iostream>   
  2. #include <memory>   
  3. using namespace std;   
  4.   
  5. int main(int argc, char **argv) {   
  6.     auto_ptr<int> ptr2(NULL);   
  7.     ptr2 = (auto_ptr<int>(new int(2)));  //調(diào)用auto_ptr_ref版本的賦值操作符   
  8. }  

#include <iostream>

#include <memory>

using namespace std;

 

int main(int argc, char **argv) {

auto_ptr<int> ptr2(NULL);

ptr2 = (auto_ptr<int>(new int(2)));  //調(diào)用auto_ptr_ref版本的賦值操作符

}

 

auto_ptr_ref之本質(zhì)

本質(zhì)上,auto_ptr_ref賦予了auto_ptr“引用”的語義,這一點(diǎn)可以從auto_ptr_ref的注釋看出:

Cpp代碼 

  1. /**  
  2.    *  A wrapper class to provide auto_ptr with reference semantics.  
  3.    *  For example, an auto_ptr can be assigned (or constructed from)  
  4.    *  the result of a function which returns an auto_ptr by value.  
  5.    *  
  6.    *  All the auto_ptr_ref stuff should happen behind the scenes.  
  7.    */  
  8.   template<typename _Tp1>   
  9.     struct auto_ptr_ref   
  10.     {   
  11.       _Tp1* _M_ptr;   
  12.          
  13.       explicit  
  14.       auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }   
  15.     };  

/**

   *  A wrapper class to provide auto_ptr with reference semantics.

   *  For example, an auto_ptr can be assigned (or constructed from)

   *  the result of a function which returns an auto_ptr by value.

   *

   *  All the auto_ptr_ref stuff should happen behind the scenes.

   */

  template<typename _Tp1>

    struct auto_ptr_ref

    {

      _Tp1* _M_ptr;

     

      explicit

      auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }

    };

 

auto_ptr_ref之代碼

這里列出auto_ptr_ref相關(guān)的函數(shù),共參考:

Cpp代碼 

  1. auto_ptr(auto_ptr_ref<element_type> __ref) throw()   
  2. : _M_ptr(__ref._M_ptr) {}   
  3.   
  4. auto_ptr&   
  5. operator=(auto_ptr_ref<element_type> __ref) throw () {   
  6.     if (__ref._M_ptr != this->get()) {   
  7.         delete _M_ptr;   
  8.         _M_ptr = __ref._M_ptr;   
  9.     }   
  10.     return *this;   
  11. }   
  12.   
  13. template<typename _Tp1>   
  14. operator auto_ptr_ref<_Tp1>() throw () {   
  15.     return auto_ptr_ref<_Tp1> (this->release());   
  16. }   
  17.   
  18. template<typename _Tp1>   
  19. operator auto_ptr<_Tp1>() throw () {   
  20.     return auto_ptr<_Tp1> (this->release());   
  21. }  

 

打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
正確使用std::auto_ptr
C++深度探索系列:智能指針(Smart Pointer)
SMART POINTER(智能指針)
C 中的健壯指針和資源管理 - 程序開發(fā) - Unix中文寶庫 Linux/Unix 中文論壇,技術(shù)討論,資料下載,休閑娛樂 -DouZhe.com - Powered by Discuz!
auto_ptr智能指針
C++智能指針auto
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服