2009-12-19 2 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 

Как-то это выглядит излишне сложным для меня. Это правда, и могу ли я сделать его лучше?

BTW, у меня есть методы 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

Желает неглубоко/глубоко скопировать карту или фигуры, которые удерживает карта? –

+0

Кто или что несет ответственность за удаление вещей, хранящихся на картах? Вся идея глубоких/неглубоких копий является чем-то вроде анти-шаблона в C++. – 2009-12-19 10:58:15

+0

Неглубокая копия shape_container должна возвращать скопированную карту, содержащую указатели на фигуры _same_. глубокая копия должна возвращать скопированную карту, содержащую указатели на фигуры _copied_. –

ответ

1

Обычно функция клонирования возвращает указатель на новый экземпляр. То, что вы возвращаете, представляет собой объект по значению, который является копией, созданной из динамически выделенного isntance, который затем просочился.

Если вы хотите вернуться по значению, то вы не должны использовать 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 также должен скопировать элементы, на которые указывает карта. –

+0

Кстати, мне не обязательно возвращаться по значению. Я просто подумал, что это хорошая идея, и это, вероятно, не было. но я хочу учиться :) –

+0

Я бы предпочел пойти с возвратом по стоимости, где мог, потому что он делает передачу прав собственности явной. Для ваших объектов 'shape' на карте это вызывает беспокойство, поскольку мелкий клон дает вам неявное совместное владение, где глубокий клон должен владеть новыми фигурами. Как вы управляете жизнью ваших фигур? –

0

Прежде всего ваш пример утечек памяти, потому что вы newshape_container в своих методах, но тогда она будет скопировано через возвращаемое значение. Вы должны возвращать указатели, как с вашим примером shape.

Ошибки компилятора как-то связаны с копированием, поскольку он жалуется, что не может создать для вас оператор присваивания. Опять же, попробуйте использовать указатели, и проблема должна исчезнуть.

0

Если вы делаете глубокую копию карты, вы должны создать новую карту создания со всем элементом с глубокой копией.

Подумайте об подход подсчета ссылок, это будет лучший подход.

+0

Я буду делать подсчет ссылок позже, но сначала я хочу, чтобы копирование работало :). но в любом случае, я хочу иметь возможность глубоко клонировать все это. –

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 ;