2

When does the object Second go out of scope? If I leave the third cout statement I get a compiler error. Even when I surround the initialization of Second and the cout statements.

#include <iostream>
using namespace std;


class MyArray{

public:
    int Size;
    int* data;

    MyArray(int s) : Size(s), data(new int[s]){}
    ~MyArray(){
        delete[](this->data);
    }
};



int main()
{

    MyArray First(20);
    First.data[0] = 25;

    MyArray Second = First;
    cout << First.data[0] << endl;
    cout << Second.data[0] << endl;
    cout << Second.data[0] << endl;



    system("PAUSE");
    return 0;

}

The runtime error: enter image description here

Quaxton Hale
  • 2,460
  • 5
  • 40
  • 71
  • 5
    A compilation error? Which one? – Mat Nov 30 '13 at 09:43
  • 5
    Also please read: http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three – Mat Nov 30 '13 at 09:45
  • I wrote this code knowing I need to write a copy constructor. I just wanted to know when `Second` goes out of scope. And why putting curly braces around the third statement doesn't work. And it is a runtime error. Debug Assertion Failed. Expression: _Block_Type_IS_valid – Quaxton Hale Nov 30 '13 at 09:52
  • @Justin If that was all your question was then why introduce the need for a copy constructor? It's irrelevant to the question of scope. – john Nov 30 '13 at 09:54
  • This isn't the problem, but `delete[](this->data)` is just a long-winded way of writing `delete [] data`. – Pete Becker Nov 30 '13 at 11:34

3 Answers3

3

Here is what's going on: MyArray objects get a pointer to their own array of integers called data upon initialization. However, this line changes things for the Second object:

MyArray Second = First;

Now both First.data and Second.data point to the same int[] array, because the default copy constructor and assignment operator perform a shallow copy.

This is bad, because the compiler has freedom to destroy First after its last use in your code. Hence, accessing Second.data[0] may be invalid already.

Moreover, once First and Second go out of scope at the end of main(), they both will try deleting data. Only the first one would succeed; the second one will trigger undefined behavior.

To avoid such errors in the future, use the rule of three. It says that if you define a destructor, a copy constructor, or an assignment operator, you probably need all three of them.

Your code has only the destructor. Adding a copy constructor and an assignment operator will fix this problem, and prevent memory leaks on assigning MyArray objects.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

The scope of both names ends at the }. (Scope is a compile-time notion.)

The lifetime of Second ends when execution reaches the end of the block, after which the lifetime of First ends. But your program has undefined behaviour because you delete the array twice, so anything can happen.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
1

You need to do the deep copy using copy constructor

MyArray(const MyArray &t)
   {

    t.size = size;
    if(size not_eq 0)
    {
    t.data = new int(size);
    for(int i=0 ; i<size ; i++)
     t.data[i] = data[i];
    }
   }

after this MyArray Second = First; will work fine if you want to assign then you have to write assignment operator as well

EmptyData
  • 2,386
  • 2
  • 26
  • 42