0

所以说我有

Class Person{
private:
    Person* _friends[10];
public:
//All methods listed below. Except for the main one, that is.
}
Person::Person()
{
    for(int i=0; i < 10; i++)
        _friends[10] = 0;
}
Person* Person::getFriends()
{
    return _friends;
}
void Person::addFriend(Person* buddy) //Assume it's fully functional.
{
    //code for adding a friend.
}
void Person::operator=(Person& p)
{
    for(int i = 0; i < 10; i++)
        _friends[i] = p.getFriends()[i];
}

int main()
{
    int user1size = 10;
    int user2size = 30;
    Person* user1 = new Person[10];
    Person* user2 = new Person[10];

    //assume these 4 next lines will be repeated with different values a few more times, in more intricate ways, by the magic of for/while loops.
    user1[0] = new Person();
    user2[9] = new Person();
    user1[0].addFriend(user[9]);
    user1[9].addFriend(user[0]); 

    for(int i = 0; i < user1size; i++)
    {
        user2[i] = user1[i]; //Here is where the paradox starts.
    }

    delete [] user1;
return 0;
}

那么好吧,我的问题是它在哪里停止?我的意思是,我的意图是只复制对 _friends 数组中的 Person 对象的引用,但我知道这可能几乎不可能,所以解决方案也是继续“复制”这些 Person 对象,而这些对象也有朋友列表,这些朋友也有朋友等等。我知道它必须在某个地方停止,但我真的不希望它一直通过,更不用说我不希望某些 Person 对象被过度复制或陷入无限循环。那么如何解决这个悖论呢?

PS:如果我的代码有很多错误或者很糟糕,请理解。我在旅途中做到了,我打算用它来让你们都了解总体思路。

PS2:我不能使用除 之外的任何其他库<ostream>,是的,这对我来说很糟糕。

PS3:任何你可以提供给我阅读的网站/文章都会让我很高兴!事先谢谢你。

4

3 回答 3

3

好吧,首先,您可能想要做的只是照原样复制指针。

为什么?因为如果人“A”有一个朋友“F”,而人“B”也有朋友“F”,那么他们可能会引用同一个人“F”对象。如果您按照您的建议进行深度复制,并将 A 复制到 A2 并将 B 复制到 B2,您将总共拥有三个不同的人“F”对象 - 原始对象,从 A 和 B 引用,副本从A2,以及从 B2 引用的另一个副本。

当然,这可能是您想要的;我不知道。但在很多情况下并非如此。

整个指针设置都可以正常工作,尽管您必须小心内存管理:您很容易得到指向不再存在的人的指针

如果您确实想要进行深度复制(“深度复制”是复制引用对象的副本),您必须自己找到循环,例如通过跟踪您已经复制的对象。我现在不会尝试绘制这样的东西,因为它可能会变得有些复杂,而且我认为您实际上并不想深度复制您的“人”对象。

于 2012-09-29T20:24:08.393 回答
1

没有悖论,因为您没有进行深度复制。查看此声明:

Person* _friends[10];

这表示 _friends 是一个指向对象的指针数组。在这个数组Person中正确复制不会调用数组中的每一个。operator=()operator=()Person

但是,以下函数将无法编译:

Person* Person::getFriends()
{
    return _friends;
}

返回类型和_friends的类型不匹配。这就是为什么发布可以编译并准确重现您遇到的问题的代码很重要的原因。

于 2012-09-29T20:38:37.150 回答
0

IIUC,您想知道如何处理对象图的副本,并且您想在图中保持它们的连接。假设 Joe 有一个朋友 Bill,Bill 有一个朋友 Joe,并且您复制 Joe(让我们将副本命名为 Joe'),您希望 Joe' 也有一个朋友,他(反射性地)将 Joe' 作为朋友。这个问题通常在编写编译器时出现。

真正做到这一点的最简单方法是永远不要做任何副本。让对象驻留在它们的内存位置,一直使用指向它们的引用/指针并破坏性地修改它们。

但是,有时需要复制对象,可能会修改图形(在编译器场景中,这可能意味着例如内联函数)。在这种情况下,您可以使用简单的图遍历算法 DFS,大致如下:

// o will be the object to copy
// m will be a map (old object -> new object)
copy(object* o, map& m) {
  if(m.contains(o))
    return m[o];
  object* n = allocate new object;
  m[o] = n; // set the map beforehand, in case we have some back edges from this subtree
  n.subobject = copy(o.subobject, m); // for each subobject, or relation. In your case, friend
  return n;
}

如果您只想将某个对象移动到新位置,则可以遍历整个图形并覆盖指针。如果您的图表中也有后边(即不仅是“朋友”,还有“我是朋友的人”),这会容易得多。尽管如此,最好的选择还是避免它。这意味着不要创建Person可能会增长的 s 数组并生成 s 数组Person*,以便 realPerson仍然保留在相同的内存位置。

于 2012-09-29T20:30:46.477 回答