2009-12-19 181 views
3

我如何最好地實現這些?我認爲是這樣的:std :: map的淺/深拷貝

using namespace std; 

    shape_container 
    shape_container::clone_deep() const 
    { 
     shape_container* ptr = new shape_container(); 
     copy(data.begin(), data.end(), (*ptr).begin()); 
     return *ptr; 
    } 

    shape_container 
    shape_container::clone_shallow() const 
    { 
     return *(new shape_container(*this)); 
    } 

成員data定義如下:

std::map<std::string, shape*> data; 

這不起作用,很遺憾。以下是編譯器錯誤,我真的不明白他們:

g++ -Wall -O2 -pedantic -I../../UnitTest++/src/ -I./libfglwin/include/ -I. -c shape_container.cpp -o shape_container.o 
    /usr/include/c++/4.2.1/bits/stl_pair.h: In member function ‘std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>& std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>::operator=(const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>&)’: 
    /usr/include/c++/4.2.1/bits/stl_pair.h:69: instantiated from ‘static _OI std::__copy<<anonymous>, <template-parameter-1-2> >::copy(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, bool <anonymous> = false, <template-parameter-1-2> = std::bidirectional_iterator_tag]’ 
    /usr/include/c++/4.2.1/bits/stl_algobase.h:315: instantiated from ‘_OI std::__copy_aux(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >]’ 
    /usr/include/c++/4.2.1/bits/stl_algobase.h:340: instantiated from ‘static _OI std::__copy_normal<<anonymous>, <anonymous> >::__copy_n(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, bool <anonymous> = false, bool <anonymous> = false]’ 
    /usr/include/c++/4.2.1/bits/stl_algobase.h:401: instantiated from ‘_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OutputIterator = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >]’ 
    shape_container.cpp:70: instantiated from here 
    /usr/include/c++/4.2.1/bits/stl_pair.h:69: error: non-static const member ‘const std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>::first’, can't use default assignment operator 
    /usr/include/c++/4.2.1/bits/stl_algobase.h: In static member function ‘static _OI std::__copy<<anonymous>, <template-parameter-1-2> >::copy(_II, _II, _OI) [with _II = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, _OI = std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*> >, bool <anonymous> = false, <template-parameter-1-2> = std::bidirectional_iterator_tag]’: 
    /usr/include/c++/4.2.1/bits/stl_algobase.h:268: note: synthesized method ‘std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>& std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>::operator=(const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, shape*>&)’ first required here 

不知怎的,這看起來過於複雜我。 是真的,我可以做得更好嗎?

順便說一句,我在我從形狀派生的類的clone()方法 。也許我可以將它們用於clone_deep方法 ?他們好嗎?他們看起來像這樣的東西 :在你的方法

所有例子
class shape 
    { 
     public: 
      /* Many methods. */ 
      virtual shape* clone() const = 0; 

     protected: 
      colorRGB color_; 
      std::string name_; 
    }; 

    class triangle2d : public shape 
    { 
     public: 
      /* Many methods. */ 
      triangle2d* clone() const; 
     private: 
      point3d a_, b_, c_; 
    }; 

    triangle2d* 
    triangle2d::clone() const 
    { 
     return new triangle2d(*this); 
    } 
+0

你想淺/深複製地圖,還是地圖保存的形狀? – 2009-12-19 10:57:27

+0

誰或負責刪除存儲在地圖中的東西?在C++中,深/淺拷貝的整體思想是一種反模式。 – 2009-12-19 10:58:15

+0

shape_container的淺拷貝應該返回一個複製的映射,包含指向_same_形狀的指針。深度複製應該返回包含指向_copied_形狀的指針的複製地圖。 – 2009-12-19 15:13:10

回答

1

通常一個克隆函數會返回一個指向新實例的指針。你正在返回的是一個按值創建的對象,它是從一個動態分配的實例中複製而來,然後被泄露。

如果您想通過要返回的值,那麼你不應該使用new。 例如

shape_container shape_container::clone_shallow() const 
{ 
    return *this; 
} 

如果data成員只是一個std::map實例,那麼它將被複製爲您的淺克隆在任何情況下的一部分,所以也沒有必要做std::copy在深克隆的情況下,它沒有試圖做任何不同的事。

如果您想要做一張地圖的std::copy,您需要使用std::insert_iterator

我想,這可能是更容易做到事後每個形狀的clone,雖然。

例如

shape_container shape_container::clone_deep() const 
{ 
    shape_container ret(*this); 

    for (std::map<std::string, shape*>::iterator i = ret.data.begin(); i != ret.data.end(); ++i) 
    { 
     i->second = i->second->clone(); 
    } 

    return ret; 
} 
+0

所以對於一個通常的淺層克隆函數,我會簡單地做'return this;'。我想這會在堆上創建一個副本?我希望clone_shallow只顯式複製容器。 deep_copy也應該複製地圖指向的元素。 – 2009-12-19 11:08:32

+0

順便說一句,我不一定需要按價值返回。我只是認爲這是一個好主意,它可能不是。但我願意學習:) – 2009-12-19 11:12:06

+0

我希望在價值回報的地方與我一起去,因爲它可以明確所有權轉移。對於映射中的「形狀」對象,這是一個值得關注的問題,因爲淺層克隆可以爲您提供隱式共享所有權,因爲深層克隆必須擁有新形狀。你如何管理你的形狀的一生? – 2009-12-19 11:28:32

0

首先泄漏內存,因爲你new一個shape_container但隨後它被通過返回的值複製出來。與您的shape示例一樣,您應該返回指針。

編譯器錯誤期待,因爲它的抱怨它不能爲你生成一個賦值操作符以某種方式來複制有關。再次嘗試使用指針,該問題應該消失。

0

如果你做了深拷貝的地圖,那麼你必須創建一個新的具有深拷貝的元素的創建地圖。

想想引用計數方法,這將是更好的辦法。

+0

我以後會做參考計算,但首先我想複製工作:)好點,但。但無論如何,我想有可能深入克隆整個事情。 – 2009-12-19 11:24:07

0

一種選擇是包裝你的形狀類型在執行對象的深 副本類型:

class shape_deep_copy_wrapper { 
    // ... 
public: 
    shape_deep_copy_wrapper (shape * shape) 
    : m_my_shape (shape) 
    { 
    } 

    shape_deep_copy_wrapper (shape_deep_copy_wrapper const & rhs) 
    : m_my_shape (rhs.m_my_shape.deep_copy()) 
    { 
    } 

    // ... 

private: 
    shape * m_my_shape; 
}; 

然後構造這種類型的地圖:

typedef std :: map < shape_deep_copy_wrapper , ... > DeepCopy ; 
typedef std :: map < shape* , ... >     ShallowCopy ;