Мелкая / глубокая копия std :: map - PullRequest
3 голосов
/ 19 декабря 2009

Как бы я лучше всего это реализовал? Я думал о чем-то вроде этого:

    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);
    } 

Ответы [ 4 ]

1 голос
/ 19 декабря 2009

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

Если вы хотите вернуть по значению, вам не следует использовать 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 голосов
/ 21 декабря 2009

Один из вариантов - обернуть ваш тип фигуры в тип, который выполняет глубокую копия объекта:

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 ;
0 голосов
/ 19 декабря 2009

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

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

0 голосов
/ 19 декабря 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...