This question already has answers here:
When to use virtual destructors?
(20 answers)
Closed 5 years ago.
I'm trying to implement autorelease pool in c++, and have trouble with deallocating.
So we have root-class object:
class object {
public:
object() {
retainCount_ = 0;
}
~object() {
std::cout << "object " << Description() << " is dealocated" << std::endl;
}
/* code with retain/release here */
int retainCount() {
return retainCount_;
}
std::string Description() {
std::stringstream ss;
ss << this;
return ss.str();
}
private:
int retainCount_;
};
And some realization:
class Integer : public object {
public:
int i;
Integer(int ii) : i(ii) {}
~Integer() {
std::cout << "Integer " << Description() << " is dealocated" << std::endl;
}
};
And of course release pool class, which works with root-class pointers:
class release_pool {
public:
void insert(object* obj) {
pointers_.insert(obj);
}
void flush() {
std::set<object*>::iterator it = pointers_.begin();
std::set<object*>::iterator tmp;
const int N = pointers_.size();
for (int i = 0; i < N; i++) {
tmp = it;
it++;
if ((*tmp)->retainCount() == 0 ) {
object* obj = *tmp;
std::cout << "delete obj: " << obj->Description() << std::endl;
pointers_.erase(tmp);
delete obj;
}
}
}
private:
std::set<object*> pointers_;
};
main.cpp code for test:
int main () {
release_pool pool;
Integer* obj = new Integer(5);
pool.insert(obj);
std::cout << "before flush: " << obj->i << "\n";
pool.flush();
std::cout << "after flush: " << obj->i << "\n";
return 0;
}
After build, I get next:
before flush: 5
delete obj: 0x7f9a84c025d0
object 0x7f9a84c025d0 is dealocated
after flush: 5
At the end: destructor of root-class is invoked, but of Integer not. Hence, we have leaked memory, which is allocated for Integer object. Have you any ideas to fix it? How i can delete whole object, not root-part of it.
You need to make your object destructor virtual.
Related
This question already has answers here:
What is object slicing?
(18 answers)
Closed 1 year ago.
I am building up a CRTP interface and noticed some undefined behavior. So, I built up some sample code to narrow down the problem.
#include <iostream>
template <typename T>
class Base {
public:
int a() const { return static_cast<T const&>(*this).a_IMPL(); }
int b() const { return static_cast<T const&>(*this).b_IMPL(); }
int c() const { return static_cast<T const&>(*this).c_IMPL(); }
};
class A : public Base<A> {
public:
A(int a, int b, int c) : _a(a), _b(b), _c(c) {}
int a_IMPL() const { return _a; }
int b_IMPL() const { return _b; }
int c_IMPL() const { return _c; }
private:
int _a;
int _b;
int _c;
};
template <typename T>
void foo(const T& v) {
std::cout << "foo()" << std::endl;
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
std::cout << "b() = " << static_cast<Base<T>>(v).b() << std::endl;
std::cout << "c() = " << static_cast<Base<T>>(v).c() << std::endl;
}
int main() {
A v(10, 20, 30);
std::cout << "a() = " << v.a() << std::endl;
std::cout << "b() = " << v.b() << std::endl;
std::cout << "c() = " << v.c() << std::endl;
foo(v);
return 0;
}
The output of this code is:
a() = 10
b() = 20
c() = 30
foo()
a() = 134217855
b() = 0
c() = -917692416
It appears that there is some problem when casting the child class, which implements the CRTP "interface", to the interface itself. This doesn't make sense to me because the class A plainly inherits from Base so, shouldn't I be able to cast an instance of A into Base?
Thanks!
You copy and slice when you cast to Base<T>.
Cast to a const Base<T>& instead:
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;
std::cout << "b() = " << static_cast<const Base<T>&>(v).b() << std::endl;
std::cout << "c() = " << static_cast<const Base<T>&>(v).c() << std::endl;
It turns out I was casting incorrectly to a value rather than a reference
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
should become
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;
I want to create a function Service that energize an exhausted phone and return it as follows.
Writing
Phone p;
p = Service(p);
does not look elegant so I want to write as follows.
Phone& p = Service(Phone());
Doing so produces weird outputs as follows.
Ctor
Dtor
Destroyed
Energy: 100%
Ending...
The expected output is:
Ctor
Energy: 100%
Dtor
Destroyed
Ending...
Question
Could you tell me why this happens?
Note: I am new to C++.
class Phone
{
private:
int energy;
bool destroyed = false;
public:
Phone() : energy{ 0 } {
cout << "Ctor" << endl;
}
~Phone()
{
cout << "Dtor" << endl;
if (destroyed == false)
{
cout << "Destroyed..." << endl;
destroyed = true;
}
}
void Energize() { energy = 100; }
void Status() const
{
cout << "Energy: " << energy << "%" << endl;
}
};
Phone& Service(Phone&& input)
{
input.Energize();
return input;
}
int main()
{
Phone& p = Service(Phone());
p.Status();
cout << "Ending..." << endl;
}
It makes no sense to return a copy of the phone. So just pass it as reference and operate on it:
void Service(Phone& phone);
Phone p{};
Service(p);
I have an abstract class Object, which looks like this:
class Object
{
public:
Object();
virtual void DoSomething() = 0;
virtual void Save(std::ofstream &file) = 0;
virtual void Load(std::ifstream &file) = 0;
};
I also have classes Ball and TextBox:
class Ball : public Object
{
public:
Ball(int x, int y, int z)
{
m_x = x; m_y = y; m_z = z;
}
void DoSomething()
{
std::cout << m_x << ", " << m_y << ", " << m_z << std::endl;
}
void Save(std::ofstream &file)
{
file << m_x << " " << m_y << " " << m_z << std::endl;
}
void Load(std::ifstream &file)
{
file >> m_x >> m_y >> m_z;
}
private:
int m_x, m_y, m_z;
};
class TextBox: public Object
{
public:
TextBox(std::string message)
{
m_message = message;
}
void DoSomething()
{
std::cout << m_message << std::endl;
}
void Save(std::ofstream &file)
{
file << m_message << std::endl;
}
void Load(std::ifstream &file)
{
file >> m_message;
}
private:
std::string m_message;
};
I have a vector of pointers to theese objects:
std::vector<Object*> objects;
objects.push_back(new Ball(1, 2, 3));
objects.push_back(new TextBox("Hello world!"));
for (Object *o : objects) o->DoSomething();
I want to save this vector to file. This is very easy. I make something like this:
std::ofstream file("foo.txt");
for (Object *o : objects) o->Save(file);
file.close();
Now I want to load this. And here is a problem. How I can specify, which object (Ball or TextBox) I supposed to load? I could use some indexes, like that:
void Ball::Save(std::ofstream &file)
{
file << 1 << " " << m_x << " " << m_y << " " << m_z << std::endl;
}
void TextBox::Save(std::ofstream &file)
{
file << 2 << " " << m_message << std::endl;
}
Then, after reading this index, I know, that this is a Ball or a TextBox.
int index;
Object *o;
file >> index;
switch (index)
{
case 1: o = new Ball(0, 0, 0); break;
case 2: o = new TextBox(""); break;
}
o->Load(file);
objects.push_back(o);
But is there a better way to store this structure? What if I have 100 inheritors of Object? Can I somehow avoid 100-switch case?
These 'indexes' you came up with are usually called 'metadata'. There are other languages, like java, that support reflection for that purpose but in C++ reflection in still under consideration. For that reason, I would suggest implementing sort of an abstract interface that would return information of the exact class of an object.
Furthermore, I would suggest looking at serialization libraries, that could ease the process of saving and reading data. You can try to start with boost:
https://www.boost.org/doc/libs/1_73_0/libs/serialization/doc/index.html
I must admit that I used boost serialization a long time ago, but I remember it was quite easy to use.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 4 years ago.
I have the following code:
class A
{
public:
int x = 6;
~A() { std::cout << "\ndestr invoked\n"; }
};
int main()
{
int* x;
{
A a;
std::cout << &a.x << "\n";
x = &a.x;
}
std::cout << x << ": " << *x;
}
With output:
0x78cac859fc00
destr invoked
0x78cac859fc00: 6
If I understand correctly it seems that destructor was invoked automatically but in memory variable remained. Does anyone know why?
In the following example (pointer was used so object was deleted manually):
class A
{
public:
int x = 6;
~A() { std::cout << "\ndestr invoked\n"; }
};
int main()
{
int* x;
{
A* a = new A;
std::cout << &a->x << "\n";
x = &a->x;
delete a;
}
std::cout << x << ": " << *x;
}
Variable was cleared:
Output:
0x1381360
destr invoked
0x1381360: 0
Does anyone know what the difference is?
I must be mistaken about something in the following code. I was experimenting, and couldn't understand why the make_shared cannot be called in the constructor, where as in initialize(), it works fine
class A {
public:
A() {
here = make_shared<A>();
}
void initialize(){
// here = make_shared<A>();
cout << &*here << endl;
cout << &here << endl;
}
void hereAddress() {
cout << &*here << endl;
}
private:
shared_ptr<A> here;
};
int main(){
vector<shared_ptr<A> > myA;
cout << "hi" << endl;
for (int i = 0; i < 10 ; ++i) {
myA.push_back(make_shared<A>() );
}
for (const auto& i : myA) {
i->initialize();
i->hereAddress();
}
return 0;
}
When I run this, I get exitcode -1. I appreicate your help.
This is because here = make_shared(); is invoking class constructor
and calling it inside constructor will make recursive calls to constructor causing segmentation faults
We need to call it outside constructor to avoid compiler complains.