4

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

我有一个带有映射的对象(称为 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;
    }

}

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

我知道 find() 函数在 const 映射上是可能的,但是我怎样才能得到我想要复制的实际对象呢?

4

6 回答 6

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

我几乎肯定这应该有效。

于 2010-10-27T15:39:11.007 回答
1

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

如果您出于某种原因需要使用map(现有 API?),您会发现operator[]只有一个非常量版本。

而是使用一种const_iterator方法(赞成并取自@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;
}
于 2010-10-27T17:10:31.467 回答
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 来解决这个问题……有点棘手,但这是你的下一个练习。

于 2010-10-27T15:50:04.330 回答
0

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

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

于 2010-10-27T15:38:18.687 回答
0
for (auto& kv : other.dataElements) {
            dataElements[kv.first] = new DataElement(*kv.second);
        }
于 2019-02-05T13:49:42.460 回答
-1

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

于 2010-10-27T15:41:40.500 回答