2012-01-12 41 views
0

如何允許帶有複製構造函數的類使用非const引用從臨時對象複製構建?如何允許臨時性的非const複製構造函數

的背景是這樣的:

我應該返回指針的列表,所有從基地繼承的對象的功能,所以我需要像vector<Base*>。 鑑於vector<auto_ptr>不是一個很好的選擇,我想寫一個簡單的包裝vector<Base*>,刪除其析構函數中的所有元素。

我面臨着以下問題:

我的類有一個拷貝構造函數如下:

auto_list(auto_list& rhs); 

,這樣我可以將指針列表複製到新的實例,並在舊的清除一。

但顯然,這不會與返回值一起工作,因爲臨時對象不會綁定到非const引用。 看到auto_ptr可以從函數返回,它們是如何實現的?

注意:我不能使用C++ 11或boost,因此移動語義或unique_ptr不是一個選項。

如果有幫助,這是我到目前爲止的代碼:

template <typename T> class auto_list 
{ 
private: 

    vector<T*> pointers; 

public: 

    auto_list(vector<T*>& pointers) 
    { 
     this->pointers = pointers; 
    } 

    auto_list(auto_list& rhs) 
    { 
     this->pointers = rhs.pointers; 
     rhs.pointers.clear(); 
    } 

    ~auto_list() 
    { 
     for(typename vector<T*>::const_iterator it = this->pointers.begin(); it != this->pointers.end(); it++) 
     { 
      delete (*it); 
     } 
    } 

    auto_list& operator=(auto_list& rhs) 
    { 
     this->pointers = rhs.pointers; 
     rhs.pointers.clear(); 
    } 

    vector<T*> get_pointers() const 
    { 
     return this->pointers; 
    } 
}; 

回答

3

這個類會比較混亂,就像auto_ptr本身一樣,我強烈建議你使用更明智的智能指針。即使你確實有一個很好的理由不使用Boost(並且對於我來說,我不知道爲什麼),那麼std::tr1::shared_ptr怎麼樣?

如果您決定繼續學習這門課程,那麼auto_ptr可以通過在課程中包裝參考(auto_ptr_ref)解決從臨時初始化的問題。包裝是由*this(它是一個左值,因此可以綁定到非const引用)的轉換函數創建的,然後可以通過值傳遞給構造函數。

你可以做同樣的事情:

template <typename T> class auto_list_ref 
{ 
    friend class auto_list<T>; 
    auto_list_ref(auto_list<T> & ref) : ref(ref) {} 
    auto_list<T> & ref; 
}; 

template <typename T> class auto_list 
{ 
public: 
    // Add a constructor and conversion operator as follows: 

    auto_list(auto_list_ref<T> rhs) 
    { 
     this->pointers = rhs.ref.pointers; 
     rhs.ref.pointers.clear(); 
    } 

    operator auto_list_ref<T>() {return auto_list_ref<T>(*this);} 
}; 

Here is a demonstration.

2

的全部原因是右值引用被髮明出來,是因爲我們不能在工作C++ 03。我的意思是,根本上,完全是破碎的。你正在努力去爭取一些無法完成的事情。堅持傳遞返回值或堆分配指針。

1

您可以聲明pointersmutable,從而允許您聲明您的副本和分配操作爲const auto_list &並仍然呼叫清除。但是,您需要謹慎使用生成的類,因爲任何副本都會清除從中複製的對象。

+0

這似乎是一個非常簡單的解決實際。有什麼可能會炸燬嗎?看到Mike Seymour的回答,我想知道爲什麼auto_ptr會使這樣的事情複雜化,而不是使用mutable。 – pezcode 2012-01-12 19:38:12

+0

然後,你將不再能夠聲明它爲'const'來防止失效,這會比'auto_ptr'更容易混淆和容易出錯。它可以通過將它傳遞給* any *函數來無效,即使該函數接受一個'const'引用。 – 2012-01-12 19:50:14

0

如果你正在努力解決缺乏std::vector<auto_ptr<Base>>與你的auto_list,我建議你完全放下課程,並寫下你自己的計數指針,它與std::vector一起工作。如果您只需要存儲Base的常見對象,則甚至可以將其引用計數,因此代碼將小於您當前正在編寫的自定義列表。

如果這不起作用,你的第二個最好的選擇可能就是採用標準在C++ 11之前處理​​的破壞方式。即通過const reference並對其做一個const_cast(yuck !!!)。如果你決定這一點,那麼要非常非常小心地使語義在任何時候都是正確的(它們會被const的東西非常容易地破壞)。