如何(深)复制const对象的地图

时间:2010-10-27 15:26:40

标签: c++ stl map const deep-copy

我还有另一个问题,我似乎无法解决......,或者在这个网站上找到......

我有一个带有地图的对象(称为DataObject),声明如下:

std::map<size_t, DataElement*> dataElements;

现在我有一个复制功能(在复制构造函数中使用):

void DataObject::copy(DataObject const &other) {

    //here some code to clean up the old data in this object...

    //copy all the elements:
    size = other.getSize();
    for(size_t i = 0; i < size; ++i) {
            DataElement* dat = new DataElement(*other.dataElements[i]);
            dataElements[i] = dat;
    }

}

这不能编译,因为在const对象上不能使用dataElements [i]。如何对const对象拥有的地图中的所有元素进行深度复制?

我知道在const地图上可以使用find()函数,但是如何找到我想要复制的实际对象?

6 个答案:

答案 0 :(得分:8)

std::map<size_t, DataElement*>::const_iterator it = other.dataElements.begin();
while(it != other.dataElements.end())
{
    dataElements[it->first] = new DataElement(*(it->second));
    ++it;
}

我几乎肯定这应该有用。

答案 1 :(得分:1)

您需要使用std :: transform。这样做的同时还对每个元素执行功能。在您的情况下,价值的深层副本。

因此,这将作为变压器:

class DeepCopyMapPointer
{
   typedef std::map<size_t, DataElement*> map_type;
   typedef map_type::value_type value_type;

public:
   value_type operator()( const value_type & other ) const
   {
      return value_type(other.first, new DataElement(*other.second) );
   }
};

void DataObject::copy(DataObject const &other) 
{
   std::transform(other.dataElements.begin(), other.dataElements.end(),
      std::inserter( dataElements, dataElements.end() ), DeepCopyMapPointer() );
}

这并不是那么简单,因为如果你复制一个元素而你的插入失败就会导致泄漏。您可以通过编写自己的插入器而不是std :: inserter来解决这个问题......有点棘手,但这是您的下一个练习。

答案 2 :(得分:1)

由于您的地图只有0n - 1的整数键,只需将容器类型更改为向量,并且您当前的代码应该可以很好地工作(您需要将目标容器的大小调整为确保有足够的空间。

如果由于某种原因需要使用map(现有API?),您发现operator[]只有非const版本。

而是使用const_iterator方法(upvoted并取自@ PigBen的答案):

std::map<size_t, DataElement*>::const_iterator it = other.dataElements.begin();
while(it != other.dataElements.end())
{
    dataElements[it->first] = new DataElement(*(it->second));
    ++it;
}

答案 3 :(得分:0)

现在没有太多时间回答所以这将是简短的。有一个map的复制构造函数,但它不会执行深层复制。您想使用迭代器(map.begin(),map.end())。 * Iter会给你一对对象,所以你可以做(​​ iter).first和/或(* iter).second。 (或类似的东西......已经有一段时间......)

参考:http://www.sgi.com/tech/stl/Map.html

答案 4 :(得分:0)

for (auto& kv : other.dataElements) {
            dataElements[kv.first] = new DataElement(*kv.second);
        }

答案 5 :(得分:-1)

只有一个观察结果: - 您可以直接访问dataElements。 (other.dataElements)。将dataElements保持为私有,然后提供类似GetDataElement的方法。