Program for class to class type conversion using conversion constructor crashed

Viewed 110

In the code below I am trying to convert int * type to vector class. But upon running the program, program terminates after a halt in the conversion constructor to copy values from int[] into vector::int *v.

Also, this is an example from one of the books. I have been trying to figure out what is happening here. Any leads would be helpful.

#include<iostream>

using namespace std;

const int size=3;

template <class T>
class vector{
    T*v;
    public:
        vector()
        {
            v=new T[size];
            for(int i=0; i<size; i++){
                cout << "A" << endl;
                v[i]=0;
            }
            cout << "vector 0-arg ctor" << endl;
        }
        vector(T *a) ///////////////////// conversion ctor for type conversion
        {
            for(int i=0; i<size; i++){
                cout << "B" << endl; 

                v[i]=a[i];////////////////// Program exits here 

            }
            cout << "vector 1-arg ctor" << endl;
        }
        T operator*(vector &y)
        {
            T sum=0;
            for(int i=0; i<size; i++){
                cout << "C" << endl;
                sum += this->v[i] * y.v[i];
            }
            return sum;
        }
};

int main(){
    int x[3]={1,2,3};
    int y[3]={4,5,6};
    vector <int> v1;
    vector <int> v2;

    v1=x; ////////////////////// Type conversion from int * -> vector
    v2=y; ////////////////////// int * -> vector

    int R=v1*v2;
    cout << "R : " << R << endl;
    return 0;
}

The output is below ->

A
A
A
vector 0-arg ctor
A
A
A
vector 0-arg ctor
B
1 Answers

At

v1=x;

Two things happen:

  1. A brand new temporary vector is constructed using vector(T *a). This temporary vector is in no way associated with v1
  2. The temporary vector is assigned to v1 using a compiler-generated default assignment operator.

Unfortunately, vector(T *a) does not allocate for v or assign existing storage to v. Since v does not point at a valid object, dereferencing it invokes Undefined Behaviour and could do anything. On the asker's computer, it looks as though v[i]=a[i]; writes into invalid memory and causes a crash. Would that we were all so lucky.

Solution

Allocate some storage for v

vector(T *a): v(new T[size])
{
    for(int i=0; i<size; i++){
        cout << "B" << endl; 
         v[i]=a[i];
    }
    cout << "vector 1-arg ctor" << endl;
}

I used a Member Initializer List as an example. It's tragically under-taught and amazingly useful.

Do not try

vector(T *a): v(a)
{
}

even though it looks very tempting. There is no way for the the vector destructor that will need to be written sometime in the near future to prevent memory leaks to be able to tell the statically allocated array x, which cannot be deleteed without invoking Undefined Behaviour, from the dynamic allocation provided by default constructor, which must be deleteed.

And since the topic of destructors have come up, it is important to be aware of the Rule of Three.

Step 2 of v1=x; performs an assignment. The compiler-generated default assignment operator is very simple and very stupid. It copies exactly what is in one vector to another. If it sees a pointer, it copies the address, not what's pointed at. Whatever was pointed at by the destination object there is not deleteed and is probably lost. This leaves you with two objects pointing to the same memory. Changing one object can now change the other and chaos ensues.

After this assignment v1's v will have been replaced by the temporary vector's, leaking v1's original memory allocation. Worse, the temporary vector lives up to the name and promptly goes out of scope. As soon as vector has a functioning destructor, the temporary will take its v with it, and since v1 and the temporary are now pointed at the same memory allocation, v1's v is left pointing at invalid memory.

An assignment operator is required to clean this mess up. See the Copy and Swap Idiom for a very simple, very safe way to write an assignment operator.

Related