What happened to this copy constructor?

I am trying to create a copy constructor for a tree. I found a lot of advice.

It interested me.

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

What does <<21> mean?

In addition, everything looks good. This is just not very good.

Any idea what's wrong with him?

The above example came from this site.

+4
source share
4 answers

Well, for starters, this is not a copy constructor - copy constructors have very clearly defined syntax in C ++, so the corresponding copy constructor will have a prototype TreeNode(TreeNode const &) . Just to get the terminology correct (and the compiler will still generate the copy constructor, since it does not know what the clone() function should do).

The expression in the if statement will highlight the new TreeNode and verify that the selection is successful (by checking that the resulting pointer is not 0). Unfortunately, this standard version of C ++ and modern C ++ implementations, which corresponds to the standard, instead generates an exception std::bad_alloc , so the test will basically give the user a warm fuzzy feeling that something is happening with a memory allocation failure, even if itโ€™snโ€™t

For the code to work properly on the standard compiler, you will have to use nothrow new. In memory, the line will read something like this:

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

All that said, if TreeNode is not part of the hierarchy of objects that relies on the presence of the clone() function, I would end it and implement my own C ++ constructor instead. Thus, the compiler and you are on the same page when it comes to duplicating objects, as well as other programmers will be a little easier to follow your code.

+10
source

I would not call the clone () method a copy constructor. For example, this is not a constructor, but only a method.

Implement a copy constructor in C ++ like this (I left all the other members to be short):

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

Edit: The above example implements / offers a shallow copy. This is what the compiler creates for you if you have not implemented the copy constructor. Therefore, if you are happy with the shallow copy, you can also leave the copy constructor.

Do you prefer a deep copy, this constructor might look like this:

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

By implementing the copy constructor, you can also mix between deep copy and shallow copy, if necessary.

+3
source

It has been a while, but if () checks if the distribution is nonempty. IE "new" succeeded.

0
source

What does if (TreeNode* tmp = new TreeNode) ?

It is supposed to check the distribution result, i.e. that he did not fail. However, this is a bad way to do this because:

  • as others have pointed out, new TreeNode will throw an exception in new C ++ compilers
  • Even if he did not select an exception, this is bad: when only some of the nodes cannot select, the calling clone() did not notice anything, but silently will receive only part of the tree.
  • When considering standard behavior, this method is an unsafe exception.
0
source

All Articles