0

Messing around in C++ for class and came across a error stating that i was trying to reference a deleted function. Here is the error

C2280(Test &Test::operator = (const Test& : attempting to reference a deleted function).

Here is my code:

#include "pch.h"
#include <iostream>

using namespace std;

class Test {
public:
    int size;
    double* array;
public: 
    Test();
    Test& operator=(Test&& a);
    Test(int sizeArg) {
        size = sizeArg;
        array = new double[size];
    }
    Test(Test&& arg) {
        size = arg.size;
        array = arg.array;
        arg.size = 0;
        arg.array = nullptr;
    }
    ~Test()
    {
        if (array != nullptr) {
            delete[]array;
        }
    }
};

int main()
{
    Test outTest;
    int x = 1;
    //Wont work since looking for a deleted function
    if (x = 1) {
        Test arg(200000000);
        outTest = arg;
    }
    cout << outTest.array;
}

The problem is in the main() on the equal sign.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 3
    `Test& operator=(Test&& a);` you declare the assignment operator but never implement it... – scohe001 Dec 04 '19 at 22:00
  • 5
    Did you mean to write `if (x == 1)` in `main()` ? `=` is the assignment operator, while `==` is the comparison-operator. – Jeremy Friesner Dec 04 '19 at 22:00
  • you don't have a copy constructor nor an assignment operator. Declaring move constructor makes them deleted by default. Or do `outTest = std::move(arg)` – Sopel Dec 04 '19 at 22:01
  • 1
    `if (array != nullptr) {` is pointless. Just `delete[] array;`. – Ted Lyngmo Dec 04 '19 at 22:03
  • gcc and clang tell you why the function is deleted. Does MSVC not do that? – eerorika Dec 04 '19 at 22:23
  • @CluelessCollegeStuden I noticed that you removed your comment to the answer you got. If anything is unclear, just ask in the comment section. I can imagine that `std::cout << outTest.array;` does not do what you'd like for example. If that's the case, just ask. – Ted Lyngmo Dec 06 '19 at 15:16

1 Answers1

2

You should get an error along these lines:

constexpr Test& Test::operator=(const Test&)’ is implicitly declared as deleted because ‘Test’ declares a move constructor or move assignment operator

This is a good thing, because the default copy assignment operator would have done a terrible job. It would have copied your pointer - and you would have ended up with two instances both claiming to own the data. Both would try to delete[] it later - with undefined behaviour as a result.

You should probably implement all 5 member functions mentioned in The rule of three/five/zero.

Example:

#include <algorithm>
#include <iostream>
#include <utility>

class Test {
public:
    int size;
    double* array;
public: 
    Test() : 
        size(0),
        array(nullptr)                    // make sure the default constructed array
                                          // is set to nullptr
    {}
    Test(int sizeArg) :
        size(sizeArg),
        array(new double[size]{})         // zero initialize the array
    {}
    // rule of five:
    Test(const Test& arg) :               // copy ctor
        size(arg.size),
        array(new double[size])
    {
        std::copy(arg.array, arg.array+size, array);
    }
    Test(Test&& arg) :                    // move ctor
        size(arg.size),
        array(std::exchange(arg.array, nullptr)) // get pointer from arg and give nullptr
                                                 // to arg
    {}
    Test& operator=(const Test& arg) {    // copy assignment operator
        Test tmp(arg);                    // reuse copy constructor
        std::swap(*this, tmp);            // let "tmp" destroy our current array
        return *this;
    } 
    Test& operator=(Test&& arg) {         // move assignment operator 
        size = arg.size;
        std::swap(array, arg.array);      // let the other object delete our current array
        return *this;
    }   
    ~Test() {
        delete[] array;                   // no "if" needed, it's ok to delete nullptr
    }
};

int main()
{
    Test outTest;
    int x = 1;

    if(x==1) {                           // use == when comparing for equality
        Test arg(2);
        outTest = arg;
    }
    std::cout << outTest.array;
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108