I have the following class, where I force the compiler to generate all the copy/move constructors and assignment operators.
class foo {
public:
    float *x;
    size_t size;
    foo(int m){
        size = m;
        x = new float[size];}
    foo(const foo&) = default;
    foo(foo&&) = default;
    foo& operator =(const foo&) = default;
    foo& operator =(foo&&) = default;
    ~foo(){delete [] x;}
    void fill(const float& num)
    {
        std::fill(x,x+size,num);
    }
    void print()
    {
        for (auto i=0;i<size;++i)
            cout << x[i] << endl;
        cout << endl;
    }
};
Then I call it from the main function, like this 
int main()
{
    foo x(2);
    x.fill(6);
    x.print();
    foo y(2);
    y = x; // causes the error
    return x;
}
Now I know I am freeing the memory twice by assigning y = x; so once one is freed the other is null, am I right? I went ahead and implemented my own copy assignment operator
foo& operator=(const foo& other)
{
    if (other.x!=x)
        x = other.x;
    return *this;
}
However, I guess here again I am doing what the default constructor is doing anyway. My question is how to make a proper copy assignment operator so that this problem does not happen?
 
    