C++ C++;:在深度复制中更新指针(高效)
我的问题最好用一个代码示例来说明,所以让我们从以下内容开始:C++ C++;:在深度复制中更新指针(高效),c++,pointers,deep-copy,C++,Pointers,Deep Copy,我的问题最好用一个代码示例来说明,所以让我们从以下内容开始: class Game { // All this vector does is establish ownership over the Card objects // It is initialized with data when Game is created and then is never // changed. vector<shared_ptr<Card> > m
class Game
{
// All this vector does is establish ownership over the Card objects
// It is initialized with data when Game is created and then is never
// changed.
vector<shared_ptr<Card> > m_cards;
// And then we have a bunch of pointers to the Cards.
// All these pointers point to Cards from m_cards.
// These could have been weak_ptrs, but at the moment, they aren't
vector<Card*> m_ptrs;
// Note: In my application, m_ptrs isn't there, instead there are
// pointers all over the place (in objects that are stored in member
// variables of Game.
// Also, in my application, each Card in m_cards will have a pointer
// in m_ptrs (or as I said, really just somewhere), while sometimes
// there is more than one pointer to a Card.
}
类游戏
{
//这个向量所做的就是建立卡对象的所有权
//它在游戏创建时用数据初始化,然后再也不会被初始化
//变了。
向量m_卡;
//然后我们有一堆指向卡片的指针。
//所有这些指针都指向m_卡中的卡。
//这些可能是薄弱的PTR,但目前并非如此
向量m_-ptrs;
//注意:在我的应用程序中,m_ptrs不存在,而是存在
//到处都是指针(在存储在成员中的对象中
//游戏变量。
//另外,在我的应用程序中,m_卡中的每个卡都有一个指针
//在m_ptrs(或者如我所说,真的只是某个地方),而有时
//指向卡片的指针不止一个。
}
现在我要做的是制作这个游戏类的深度副本。我制作了一个新的向量,其中包含新的共享ptr,它指向新的卡对象,这些卡对象是原始卡对象的副本。这一部分很简单
然后问题开始了,m_PTR的指针应该更新为指向m_卡中的卡,这不是简单的任务
我能想到的唯一方法是创建一个映射并在复制m_卡时填充它(使用map[oldPtr]=newPtr
),然后使用它来更新m_ptr。然而,这只是O(m*log(n))
(m=m_ptrs.size();n=m_卡.size()
)。由于这将是一个非常常规的操作*我希望能有效地执行此操作,我觉得在O(m)
中使用自定义指针应该是可能的。但是,我似乎找不到一种有效的方法来执行此操作。有人这样做吗
*它被用来为人工智能创建一个测试平台,让它“尝试”不同的动作
编辑:我想补充一点关于接受答案的内容,因为我还没有回答。我一直在等待,直到我回到这个项目(因为我在这个项目上做了太多的工作,所以我走上了一条岔路——如果你是为了乐趣而做的,那就必须保持乐趣),所以我可能需要一段时间才能接受答案。不过,我会在某个时候接受答案,所以不要担心:P
编辑NR2:我还没有回到这个项目。现在,我正在考虑只取
O(m*log(n))
way,不要抱怨,然后再看看是否需要更快。然而,由于我最近花了一些时间学习我的模式,我也在想,我真的需要在某个时候重构这个项目。哦,我可能会花一些时间用我掌握的所有新知识来解决这个问题。因为没有一个回答是“坚持使用hashmap,看看它是否真的需要更快”(如果有,我会非常失望,因为这不是我问题的答案),我会推迟选择答案,直到我回到这个项目
编辑nr 3:我仍然没有回到这个项目。更准确地说,它已经被无限期搁置。我非常确定我不会对
O(m*log(n))太低头
现在,如果发现问题,也许以后再看。但是,这不是我问题的好答案,因为我明确要求提高性能。我不想让答案不再被接受,我选择了最有用的答案并接受了它。将指针存储为索引。
正如你所说,它们都指向m_卡片,这是一个可以被索引的向量(这是正确的英语吗?)。
或者只在存储时这样做,然后在加载时将它们转换回指针。
或者您可能会考虑通常使用索引而不是指针。将卡片元素保留为索引而不是指针怎么样: vector<int> m_indexes; ... Card* ptr = &m_cards[m_indexes[0]]; 向量m_指数; ... 卡片*ptr=&m_卡片[m_索引[0]];
带有索引的向量可以不加更改地复制。我最近遇到了非常类似的问题:克隆由指针和std::Vector实现的类内部结构作为对象存储 首先(与问题无关),我建议要么使用智能指针,要么使用简单结构。在你的例子中,这意味着使用
向量m_ptrs
而不是原始指针更有意义
关于问题本身-另一个可能的解决方法是在复制构造函数中使用指针差异。我将为对象向量演示它,但使用共享指针将使用相同的原理,唯一的区别是复制m_卡(如果需要对象克隆,不应简单地使用赋值,而应逐个元素复制m_卡)
非常重要的一点是,该方法仅适用于保证存储元素的容器(向量、数组)
另一个非常重要的时刻是m_ptr
元素应仅表示内部卡结构,即它们必须仅指向内部m_卡元素
// assume we store objects directly, not in shared pointers
// the only difference for shared pointers will be in
// m_cards assignment
// and using m_cards[...].get() instead of &m_cards[...]
vector<Card> m_cards;
vector<Card*> m_ptrs;
//假设我们直接存储对象,而不是存储在共享指针中
//共享指针的唯一区别在于
//m_卡分配
//并使用m_卡[…]。get()而不是&m_卡[…]
向量m_卡;
向量m_-ptrs;
在这种情况下,可以通过使用指针算术(使用线性时间)轻松计算指针数组。在这种情况下,复制构造函数将如下所示:
Game::Game(const Game &rhs) {
if (rhs.m_cards.empty())
return;
m_cards = rhs.m_cards;
// if we have vector of shared pointers
// and we need vector of pointers to objects clones
// something like this should be done
// for (auto p: rhs.m_cards) {
// // we must be certain here that dereferencing is safe,
// // i. e. object must exist. If not, additional check is required.
// // copy constructor will be called here:
// m_cards.push_back(std::make_shared<Card>(*p));
// }
Card *first = &rhs.m_cards[0];
for (auto p: rhs.m_ptrs) {
m_ptrs.push_back(&m_cards[p - first]);
}
}
Game::Game(const-Game和rhs){
if(rhs.m_cards.empty())
返回;
m_卡=rhs.m_卡;
//如果我们有共享指针的向量
//我们需要指向对象克隆的指针向量
//应该这样做
//用于(自动p:rhs.m_卡){
////在这里,我们必须确定取消引用是安全的,
////即对象必须是