4

私はツリーのコピーコンストラクターを考え出そうとしています。私はかなりの数の提案を見つけました。

これは私に興味を持った。

class TreeNode
{
    int ascii;
    TreeNode* left;
    TreeNode* right;

public:
    TreeNode() { ascii = 0; left = right = 0; }
    TreeNode* clone();
    // ...
};

 TreeNode* TreeNode::clone()
    {
        if (TreeNode* tmp = new TreeNode)
        {
            tmp->ascii = ascii;
            if (left) tmp->left = left->clone();
            if (right) tmp->right = right->clone();
            return tmp;
        }
        return 0;
    }

とはif (TreeNode* tmp = new TreeNode)どういう意味ですか?

それ以外は問題ないようです。うまく機能しません。

何が問題なのですか?

上記の例は、このサイトからのものです。

4

4 に答える 4

10

まず、コピー コンストラクターではありません。コピー コンストラクターは C++ で非常に明確に定義された構文を持っているため、適切なコピー コンストラクターにはプロトタイプが含まれTreeNode(TreeNode const &)ます。clone()用語を正しく理解するためだけです (コンパイラは、関数が何をすべきかわからないため、コピー コンストラクタを生成します)。

if ステートメントの式は、新しい TreeNode オブジェクトを割り当て、割り当てが成功したことを確認することを目的としています (結果のポインターが 0 でないことを確認することによって)。残念ながら、これは標準に準拠する前の C++ および最新の C++ 実装では、std::bad_alloc代わりに例外がスローされるため、テストは主に、メモリ割り当ての失敗について何かが行われているという温かいあいまいな感覚をユーザーに与えます。

標準準拠のコンパイラでコードが期待どおりに機能するようにするには、notthrow new を使用する必要があります。メモリから、行は次のようになります。

if (TreeNode* tmp = new(std::nothrow) TreeNode)

つまり、TreeNode が関数の存在に依存するオブジェクト階層の一部でない限り、clone()私はそれを廃止し、代わりに適切な C++ コンストラクターを実装します。そうすれば、オブジェクトの複製に関してコンパイラとあなたは同じページにいるだけでなく、他のプログラマーもあなたのコードを追うのが少し簡単になります。

于 2010-08-06T01:11:44.937 に答える
3

clone() メソッドをコピー コンストラクターとは呼びません。たとえば、そもそもコンストラクターではなく、単なるメソッドです。

次のように C++ でコピー コンストラクターを実装します (短くするために、他のすべてのメンバーを省略しました)。

class TreeNode {
    public:
       TreeNode(const TreeNode& source) {
          // copy members here, e.g.
          left = source.left;
          ...
       }
};

編集:与えられた例は、浅いコピーを実装/提案しています。これは、コピー コンストラクターを実装していない場合にコンパイラが作成するものです。したがって、浅いコピーに満足している場合は、コピー コンストラクターを省略してもかまいません。

ディープ コピーを好む場合、このコンストラクタは次のようになります。

class TreeNode {
   public:
      TreeNode(const TreeNode& source) {
         left = source.left != NULL ? new TreeNode(*source.left) : NULL;
         ...
      }

コピー コンストラクターを実装することで、必要に応じてディープ コピーとシャロー コピーを混在させることもできます。

于 2010-08-06T01:07:50.283 に答える
0

しばらく経ちましたが、if () は、割り当てが null でないかどうかをチェックしています。IE「新しい」が成功しました。

于 2010-08-06T01:05:13.267 に答える
0

とはif (TreeNode* tmp = new TreeNode)どういう意味ですか?

これは、割り当ての結果をチェックすることになっています。失敗していないこと。ただし、次の理由から、これは悪い方法です。

  1. 他の人が指摘したようにnew TreeNode、新しい C++ コンパイラでは例外がスローされます
  2. 例外がスローされなかったとしても、それは悪いことです: 一部のノードのみが割り当てに失敗した場合、 の呼び出し元はclone()何も気付かず、黙ってツリーの一部のみを取得します。
  3. 標準的な動作を考慮すると、このメソッドは例外的に安全ではありません。
于 2010-08-06T01:23:29.347 に答える