I'm catching up with modern C++, practicing move semantics.
I made a very simple test case:
- create an instance
- move-construct a new instance
I noticed that when my instances are destroyed, both destructors are called:
- the one of the move-constructed instance, where data is a valid pointer
- the one of the original instance, where the data pointer was deleted and set to nullptr when it was moved
My code deleting a nullptr makes me uncomfortable, here are the questions:
- is that (deleting nullptr) even a valid operation (i.e. does that result in UB; will it eventually crash my application)?
- or is my move-constructor / move-assignement operator definition wrong?
- I found this similar question, but it is still not clear, in particular if deleting a nullptr is a problem. Should I avoid that by checking the pointer in the destructor? If so, it feels like using move semantics causes kind of systematic wrong behavior.
My output for the test (code below) is:
Test 5
new 0x7512b0
move_new 0x7512b0
delete[] 0x7512b0
delete[] 0
The delete[] 0 output is what grinds my gears.
Here's the main:
#include <iostream>
#include "test5.h"
int main()
{
std::cout << "Test 5" << std::endl;
test5 rule5;
test5 rule5move = std::move(rule5);
// rule5 = std::move(rule5move);
return 0;
}
and here's test5.h:
#ifndef TEST5_H
#define TEST5_H
class test5
{
public:
test5(): data(new float[10]){
std::cout << "\tnew " << data << std::endl;
for (int i = 0; i < 10; i++)
data[i] = float(i);
}
~test5(){
std::cout << "\tdelete[] " << data << std::endl;
delete[] data;
}
// copy constructor
test5(const test5& t) : data(new float[10]){
std::cout << "\tcopy " << data << std::endl;
std::copy(t.data, t.data + 10, data);
}
// copy operator
test5& operator=(const test5& t){
std::cout << "\tassign " << data << std::endl;
std::copy(t.data, t.data + 10, data);
return *this;
}
// move constructor
test5(test5&& t): data(new float[10]){
delete[] data;
data = t.data;
std::cout << "\tmove_new " << data << std::endl;
t.data = nullptr;
}
// move operator
test5& operator=(test5&& t){
delete[] data;
data = t.data;
std::cout << "\tmove_assign " << data << std::endl;
t.data = nullptr;
return *this;
}
private:
float* data;
};
#endif // TEST5_H
Aucun commentaire:
Enregistrer un commentaire