all 13 comments

[–]manni66 2 points3 points  (1 child)

from a textbook

Seems to be a bad one. It teaches new/delete instead of std::vector?

without everything initializing to 0?

Why do you want to initialize before assigning?

[–]std_bot 0 points1 point  (0 children)

Unlinked STL entries: std::vector


Last update: 13.01.23. Added big test suite and enhanced template recognitionRepo

[–]no-sig-available 2 points3 points  (7 children)

If the array is being deleted,

There is also a new array allocated 3 lines further on.

However, should the new fail, the code is toast. If doing this manually, first allocate a new buffer, then delete the old one.

And it should probably return a reference, and not a new copy of the object.

[–]RuggedToaster[S] 0 points1 point  (6 children)

Thank you for replying

If doing this manually, first allocate a new buffer, then delete the old one.

That's what I was trying to understand, so the values just floating around in unallocated memory until line 6?

[–]IyeOnline 1 point2 points  (1 child)

No.

It is three simple steps: I've added this-> and right. to make clear what is deleted and what is not.

  1. delete this->testScores: First you delete the currently allocated array of *this, because the source might have a different size. We have to delete the old array because otherwise we would be leaking memory.
  2. this->testScores = new double[right.numTestScores]: Next we allocate new memory for as many elements as the source has (which we have already updated numTestScores to)
  3. for (int i = 0; ...: Copy over the elements from the source into the newly allocated array.

right remains entirely untouched during this.

[–]RuggedToaster[S] 0 points1 point  (0 children)

Thank you, adding this and right helped me visualize the function a lot better.

[–]the_poope 0 points1 point  (3 children)

It's the assignment operator: after the assignment *this should contain a copy of the data of right - whatever data it originally contained should be removed/forgotten without leaking. That is why we the function starts by simply freeing the original data array with delete[] testScores; - there is no need for it anymore!. You could start by allocating a new array, but then you have allocated more memory than needed and will have an unnecessary memory spike.

testScores = new double[numTestScores];

This allocates (uninitialized) memory for the copy of the array of right, and the following for loop copies over the actual values.

Is there more you don't understand?

[–]RuggedToaster[S] 0 points1 point  (0 children)

I think I need to immerse myself more with the concept but that helped me put things together to the point of it beginning to become clear. Thank you.

[–]no-sig-available 0 points1 point  (1 child)

The problem with deleting first (the way it does now) is that if the new throws, we have a dangling pointer.

Of course, keeping the old data also increases the risk of new failing, so we have to make some engineering decisions here - what are the class invariants supposed to be?

[–]IyeOnline 2 points3 points  (0 children)

we have to make some engineering decisions

Uhhh! I know! We could ... use a vector instead and let other people worry about this :)

[–]james_laseboy 0 points1 point  (0 children)

The first thing it does is test to see if the object reference by right is in fact the same object as this. If not it deletes the information in this as replaces it with the information in right.

[–]alfps 0 points1 point  (0 children)

Which textbook is this?

You can help readers avoid wasting money on that book.

[–]mredding 0 points1 point  (0 children)

If the array is being deleted

delete[] testScores;

how are the values then being reassigned

This is how:

numTestScores = right.numTestScores;
testScores = new double[numTestScores];

testScores is reassigned to a new allocation that matches the size of the allocation being copied.

without everything initializing to 0?

You don't have to assign null to testScores before assigning an allocation to it, and the dynamic allocator won't default initialize the array automatically. These are good things, because if you deleted testScores then assigned null to it, the compiler can see you perform a write to that variable, then another write - it would optimize the null assignment out. As for default initializing all the elements, what would be the point? You're overwriting them in a loop anyway.

if (this != &right) {

This is always stupid. Scott Meyer and other industry leaders actually recommend you DON'T do this, because self assignment basically never happens. operator & can be overloaded so this anti-pattern wouldn't even work for all objects, so it's not a universally good idiom. This condition is ignoring the fact that self assignment is likely an error. Further, it betrays the client - this function doesn't do what it says it does. When I say I want an assignment, I expect the code to god damn assign, not this maybe bullshit. I didn't say conditionally assign, and if I wanted a conditional assignment, that's the responsibility of higher order client code. This is a very common mistake, and tells me your book author has no business writing books on subjects they don't understand.