-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Destructor is called when filling object through assignement #1050
Comments
You see two destructor calls, because there are two objects created: #include <iostream>
#include "json.hpp"
using json = nlohmann::json;
class State {
public:
State() : x(0.0) {
std::cout << "default constructed" << std::endl;
}
State(const State &o) : x(o.x) {
std::cout << "copy constructed" << std::endl;
}
State(State &&o) : x(o.x) {
std::cout << "move constructed" << std::endl;
}
State& operator=(const State &o)
{
std::cout << "copy assign" << std::endl;
x = o.x;
return *this;
}
State& operator=(State &&o)
{
std::cout << "move assign" << std::endl;
x = o.x;
return *this;
}
~State() {
std::cout << "destroyed" << std::endl;
}
double x;
};
void from_json(const json& j, State& p) {
try {
p.x = j.at("x").get<double>();
} catch(json::type_error& e) {
std::cout << e.what() << std::endl;
} catch(json::out_of_range& e) {
std::cout << e.what() << std::endl;
}
}
int main() {
json data;
State s;
data["x"] = 10.;
s = data;
std::cout << s.x << std::endl;
return 0;
} Output:
The first object is created with The following code avoids this: int main() {
json data;
data["x"] = 10.;
State s = data;
std::cout << s.x << std::endl;
return 0;
} |
Thank you very much for immediate response! Actually, I had a bit more complicated situation. I'm freeing memory for some properties in the destructor. So the way out is to implement own move-assignment operator, hence move-constructor as well. Is it right workaround? #include <iostream>
#include <string>
#include "nlohmann/json.hpp"
using namespace std;
using json = nlohmann::json;
class State {
public:
string* x;
State() {
x = new string("hello");
}
State(State &&from) {
x = from.x;
from.x = nullptr; // delete does nothing with nullptr starting from c++14
}
State& operator=(State &&from) {
if (this == &from) {
return *this;
}
x = from.x;
from.x = nullptr;
return *this;
}
~State() {
cout << "destroyed" << endl;
delete x;
}
};
void from_json(const json& j, State& p) {
try {
*p.x = j.at("x").get<string>();
} catch(json::type_error& e) {
std::cerr << e.what() << std::endl;
} catch(json::out_of_range& e) {
std::cerr << e.what() << std::endl;
}
}
int main() {
json data;
State s;
data["x"] = "world";
s = data;
cout << *s.x << endl;
return 0;
} Now it works. And output is:
Thank you again! |
I think so. I'm not sure whether you'd need to call |
Yes. Sounds reasonable. Thank you for review :) I like the library very much! |
Bug Report
What is the issue you have?
Destructor being called in an unexpected place.
Please describe the steps to reproduce the issue. Can you provide a small but working code example?
Output is:
What is the expected behavior?
do not call destructor during assignment
And what is the actual behavior instead?
destructor is called
Which compiler and operating system are you using? Is it a supported compiler?
develop
branch?checked for both: master and develop branch.
Could you please describe, whether it is a feature or a bug :) By default assignment operator doesn't call destructor, that is why the behavior seems to me unexpected.
Thank you!
The text was updated successfully, but these errors were encountered: