复制构造函数问题Lippman

时间:2010-07-21 12:38:24

标签: c++ constructor copy

我试图解决一个副本ctro qs在lipman中给出n不确定如果我做对了。由于课程有自己的指针,它让我有点困惑。这是代码

#include <iostream>
#include <string>

using namespace std;

class BinStrTreeNode{

      public:
         BinStrTreeNode(const string& val):_val(val){ 
              _leftchild = new BinStrTreeNode("nup");
              _rightchild = new BinStrTreeNode("rup");
              cout << "ctor" << endl;
         };
         BinStrTreeNode(const BinStrTreeNode&);
     private:
         string _val;
         BinStrTreeNode *_leftchild;
         BinStrTreeNode *_rightchild;
};

BinStrTreeNode::BinStrTreeNode(const BinStrTreeNode& rhs):_val(rhs._val){
    cout << "copy ctor" << endl;
    _leftchild = new BinStrTreeNode(*(rhs._leftchild));
    _rightchild = new BinStrTreeNode(*(rhs._rightchild));
}

它给出了分裂错误。我知道我也需要定义一个dtor,但首先我需要做到这一点。我该如何为这样的类定义复制ctor,赋值运算符?

由于

3 个答案:

答案 0 :(得分:2)

你得到的基本上是正确的。
你只是忘了检查NULL指针。

BinStrTreeNode::BinStrTreeNode(const BinStrTreeNode& rhs)
    :_val(rhs._val)
    ,_leftchild(NULL)
    ,_rightchild(NULL)
{
    cout << "copy ctor" << endl;
    if (rhs._leftchild  != NULL) {_leftchild  = new BinStrTreeNode(*(rhs._leftchild));}
    if (rhs._rightchild != NULL) {_rightchild = new BinStrTreeNode(*(rhs._rightchild));}
}

注意树不会指向树中更高(或自我)的节点(因为它将不再是树,它将成为图形)。如果您的代码是图形,那么您需要重新编写此代码,以便进行图形复制,因为您需要跟踪已在地图中复制的节点,因此复制要复杂得多。

虽然我个人会更进一步,并在初始化列表中执行所有操作:
虽然我只是说这是个人偏好。

BinStrTreeNode::BinStrTreeNode(const BinStrTreeNode& rhs)
    :_val(rhs._val)
    ,_leftchild ((rhs._leftchild  == NULL)?NULL:new BinStrTreeNode(*(rhs._leftchild)))
    ,_rightchild((rhs._rightchild == NULL)?NULL:new BinStrTreeNode(*(rhs._rightchild)))
{
    cout << "copy ctor" << endl;
}

循环树(AKA图)

让我们从头开始:
在这种情况下,我们需要跟踪我们创建的每个节点。然后,当一个指针指向已经被复制的节点时,我们使用复制的节点而不是创建一个新的节点(否则我们最终会在循环之后和周围的周围发生递归噩梦)。

typedef std::map<BinStrTreeNode*,BinStrTreeNode*>   CopyMap;
BinStrTreeNode::BinStrTreeNode(const BinStrTreeNode& rhs)
    :_val(rhs._val)
{
    CopyMap    copyMap;
    copyMap[&rhs] = this;

    left  = copyGraph(left,copyMap);
    right = copyGraph(right,copyMap) 
}

private:
BinStrTreeNode* BinStrTreeNode::copyGraph(BinStrTreeNode* node,CopyMap& copyMap)
{
    if (node == NULL)
    {    return NULL;
    }

    if (copyMap[node] != NULL)
    {    return copyMap[ndoe];
    }

    return new BinStrTreeNode(*node, copyMap);
}
BinStrTreeNode::BinStrTreeNode(const BinStrTreeNode& rhs, CopyMap& copyMap)
    :_val(rhs._val)
{
    copyMap[&rhs] = this;
    left  = copyGraph(left,copyMap);
    right = copyGraph(right,copyMap) 
}

答案 1 :(得分:1)

您的复制构造函数是递归的。您可能已经耗尽内存或者有新的内存异常,或者很可能在其中一个复制构造函数调用中取消引用了空指针。

答案 2 :(得分:1)

你的主要问题是两个构造函数都无限地递归:

  • 您的构造函数将递归,直到您获得堆栈溢出,或直到new抛出std::bad_alloc
  • 你的拷贝构造函数会递归,直到你得到一个堆栈溢出,或者直到它遇到一个无效的左子或右子,它会发生段错误。

您的潜在问题是您的递归函数没有终止条件。所有函数(包括构造函数)都需要一个不递归的代码路径。