2009-12-19 2180 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 ;