This is a follow up on my previous question posted here (C++ vector of class objects and dynamic memory allocation).
Someclass
is an oversimplified class for the sake of this example. Important to know that objects of this class are stored in a vector somewhere else.
Buffer
is another class that has three types of members: regular variables (NAME), vectors (S), and pointers to dynamically allocated memory blocks (DATA).
If I comment v.erase(v.begin()+1);
line then code compiles and runs fine. Bur erase
produces a number of errors such as "use of deleted function Buffer& Buffer::operator=(const Buffer&)
".
I think I understand the issue but do not know how to fix it. Would you please modify my example to make it work? Note, that the example is oversimplified and I need to keep these two classes and use of vectors.
Thank you.
using namespace std;
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;
class Someclass
{
public:
int I;
Someclass(int i) {I = i;};
private:
};
class Buffer
{
public:
vector <Someclass> S;
string NAME;
float *DATA;
Buffer(int length, string name) {DATA = (float*) calloc (length,sizeof(float)); NAME = name;};
Buffer(const Buffer &buffer) = delete;
Buffer(Buffer&& buffer) {
S = buffer.S;
NAME = buffer.NAME;
DATA = buffer.DATA;
buffer.DATA = nullptr;
}
~Buffer(){
S.clear();
if (DATA) free(DATA);
};
private:
};
int main(int argc, char** argv)
{
vector <Buffer> v;
for (int i =0; i<10; i++)
{
cout<<i<<endl;
v.push_back(Buffer(1000,"name"));
}
v.erase(v.begin()+1);
v.clear();
return 0;
}
This is because of a simple reason. When you erase an entry, the array needs to remove that "bubble" (which is the empty slot) and compact the array. Which means that it needs to move some stuff. So when moving, what they do is something like this,
// Form the MSVC xutility.h file.
for (; _First != _Last; ++_Dest, (void) ++_First) {
*_Dest = _STD move(*_First);
}
As you can see, the way they move it is by moving the individual entries. This means that you call the copy assign/ move assign operator of the object Buffer
. But you haven't defined any assignment operators, but a move constructor. This tells the compiler that,
"Hey, this Buffer object only has a move constructor. Maybe the user just wants to construct the class by moving another. So it cant have any other assignments (both copy and move)"
So now the compiler doesn't generate them for you. This means that you now cant copy or move another Buffer
to another (unless you move construct it). That's the reason for the error.
The solution is to add a move assign operator.
Buffer& operator=(Buffer&& other)
{
S = std::move(other.S);
NAME = std::move(other.NAME);
DATA = other.DATA;
other.DATA = nullptr; // Make sure to set it to nullptr.
return *this;
}