2011-09-09 74 views
6

我瞭解到STL可以禁止程序員將auto_ptr放入容器中。例如下面的代碼不會編譯:爲什麼vector.push_back(auto_ptr)不能編譯?

auto_ptr<int> a(new int(10)); 
    vector<auto_ptr<int> > v; 
    v.push_back(a); 

auto_ptr有複製構造函數,爲什麼這個代碼甚至可以編譯?

+1

我知道我不應該在stl中使用auto_ptr,因爲複製語義。但我的問題是** stl是如何實現的,所以它可以禁止你這樣做?**在我的示例代碼中,它甚至不能編譯。 – frinker

+1

你可以發佈編譯錯誤嗎? –

+0

@xanatos:沒有拷貝構造函數是'const'! –

回答

11

看着the definition of std::auto_ptr

namespace std { 

    template <class Y> struct auto_ptr_ref {}; 


    template <class X> 
    class auto_ptr { 
    public: 
     typedef X element_type; 

     // 20.4.5.1 construct/copy/destroy: 
     explicit   auto_ptr(X* p =0) throw(); 
          auto_ptr(auto_ptr&) throw(); 
     template <class Y> auto_ptr(auto_ptr<Y>&) throw(); 

     auto_ptr&      operator=(auto_ptr&) throw(); 
     template <class Y> auto_ptr& operator=(auto_ptr<Y>&) throw(); 
     auto_ptr&      operator=(auto_ptr_ref<X>) throw(); 

     ~auto_ptr() throw(); 

     // 20.4.5.2 members: 
     X&  operator*() const throw(); 
     X*  operator->() const throw(); 
     X*  get() const throw(); 
     X*  release() throw(); 
     void reset(X* p =0) throw(); 

     // 20.4.5.3 conversions: 
            auto_ptr(auto_ptr_ref<X>) throw(); 
     template <class Y> operator auto_ptr_ref<Y>() throw(); 
     template <class Y> operator auto_ptr<Y>() throw(); 
    }; 

} 

雖然有一個複製構造函數,但需要參考const。臨時工不得與此綁定,因此在任何使用臨時工的地方禁止在集裝箱內工作;此外,push_back接受對const的引用,所以由於const-正確性,新的內部元素不可能通過從push_back的參數複製構建。

(維基百科頁面上說「因爲它的複製語義,auto_ptr可能不能在可能在其操作中執行元素拷貝的STL容器中使用」;這並不意味着容器會奇蹟般地檢查拷貝構造函數中的代碼決定是否希望使工作類型爲元素的類型。相反,它只是函數簽名。)

反正std::auto_ptr被棄用的C++ 11,因爲,在一些人看來,std::auto_ptr是愚蠢。對不起,std::auto_ptr

+0

+1,這裏也討論了:http://stackoverflow.com/q/3316514 – sharptooth

+1

我強烈反對,std :: auto_ptr是解決一組問題的完美選擇。可悲的是開發者濫用它。 –

+0

+1,我明白了,謝謝你! – frinker

0

因爲std :: auto_ptr與stl容器不兼容。

的std :: auto_ptr的是使用單一所有權拷貝語義的STL容器需要拷貝構造一個對象(和一些算法需要指定它)

您應該使用計數智能指針的引用(升壓:: shared_ptr的)

EDIT

例如,這是的push_back的簽名

void push_back (const T& x); 

問題是,std :: auto_ptr是特殊的,複製構造函數和賦值運算符簽名是不同的。它們不是常量。如果您複製它,則修改auto_ptr。

auto_ptr& operator= (auto_ptr& a) throw(); 

auto_ptr (auto_ptr& a) throw(); 

您無法提供滿足push_back要求的auto_ptr。

+0

或者像'std :: unique_ptr'這樣的具有移動語義的體面的單一所有權指針。 –

+0

查看Effective C++的項目13-17,它不是專用於auto_ptr,但它對了解您的問題非常有用。 –

+3

我知道我不應該在stl中使用auto_ptr,因爲複製語義。但我的問題是** stl是如何實現的,所以它可以禁止你這樣做?**在我的示例代碼中,它甚至不能編譯。 – frinker

0

其他答案是關於auto_ptr爆炸。

做你正在嘗試做的使用std ::的unique_ptr如果提供給你(C++ 11),如果不是,你可以使用一個shared_ptr

6

關於編譯器如何檢測這種情況(或STL如何導致錯誤)的特定問題,您應該閱讀編譯器的確切輸出,它將包含一系列將導致失敗的錯誤執行從const XX的轉換,因爲它會丟棄const限定符,其中X可以是std::auto_ptr<>,也可以是內部詳細信息類型。

特別地,通過std::vector::push_backconst &取參數,並在內部將嘗試複製構建使用可用的拷貝構造,這在std::auto_ptr的情況下需要非const引用動態數組中的元素。行內的東西:

void push_back(std::auto_ptr<int> const & x) { 
    // ensure enough capacity if needed... 
    new (buffer + size()) std::auto_ptr<int>(x); // !!! cannot bind x to non-const& 
    // complete the operation (adjust end pointer, and such) 
}