如何从 const 对象(深度)复制映射

发布于 2024-09-29 13:45:34 字数 688 浏览 1 评论 0原文

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

我有一个带有地图的对象(称为 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 映射上使用,但是如何获取我想要复制的实际对象呢?

I have another problem I can't seem to solve..., or find on this site...

I have an object (called DataObject) with a map, declared as follows:

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

Now i have a copy function (used in the copy constructor):

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

}

This doesn't compile, since dataElements[i] is not possible on a const object. How do I make a deep copy of all the elements in the map that is owned by a const object?

I know that the find() function is possible on a const map, but then how do I get to the actual object that I want to copy?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

把梦留给海 2024-10-06 13:45:34
std::map<size_t, DataElement*>::const_iterator it = other.dataElements.begin();
while(it != other.dataElements.end())
{
    dataElements[it->first] = new DataElement(*(it->second));
    ++it;
}

我几乎肯定这应该有效。

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

I'm almost positive this should work.

小鸟爱天空丶 2024-10-06 13:45:34

您需要使用 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 来解决这个问题...有点棘手,但这是您的下一个练习。

You need to use std::transform. This does a copy whilst also performing a function on each element. In your case a deep copy of the value.

This will therefore do as a transformer:

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

It's not quite that simple because if you do duplicate an element and your insert fails as a result you will get a leak. You could get round that by writing your own inserter instead of std::inserter... a bit tricky but that's your next exercise.

恋竹姑娘 2024-10-06 13:45:34

由于您的地图只有从 0n - 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;
}

Since your map just has integer keys from 0 to n - 1, just change your container type to a vector, and your current code should work nicely (you'll need to resize the destination container to make sure there's enough room available).

If you need to use map for some reason (existing API?), as you discovered operator[] has only a non-const version.

Instead use a const_iterator approach (upvoted and taken from @PigBen's answer):

std::map<size_t, DataElement*>::const_iterator it = other.dataElements.begin();
while(it != other.dataElements.end())
{
    dataElements[it->first] = new DataElement(*(it->second));
    ++it;
}
情释 2024-10-06 13:45:34

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

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

Don't have much time to answer now so this will be brief. There is a copy-constructor for map, but it won't do a deep copy. You want to use iterators (map.begin(), map.end()). *Iter will give you a pair object, so you can do (*iter).first and/or (*iter).second. (Or something like that... It's been a while...)

Ref: http://www.sgi.com/tech/stl/Map.html

战皆罪 2024-10-06 13:45:34
for (auto& kv : other.dataElements) {
            dataElements[kv.first] = new DataElement(*kv.second);
        }
for (auto& kv : other.dataElements) {
            dataElements[kv.first] = new DataElement(*kv.second);
        }
羅雙樹 2024-10-06 13:45:34

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

Just one observation :- You are giving direct access to the dataElements. (other.dataElements). Keep dataElements private and then give method like GetDataElement.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文