In C++, whose responsibility is it to delete members of a class: the class, or the creator of an instance of that class?
For example, in the following code:
class B {
public:
B(int x) { num = x; }
int num;
};
class A {
public:
A(B* o) { obj = o; }
B* obj;
};
int main(void) {
A myA(new B(3));
return 0;
}
Should main delete the instance of B, or should A's destructor delete its local variable obj? Is this true in most cases, and in which cases if any is it not?
This is a basic question of ownership. If every A should own a B (as in, there should be a new B created when the A is created, that should also be destroyed be the A is destroyed, then you'd normally make A responsible for creating and destroying the instance of B:
class B {
int num;
public:
B(int x) : num(x) {}
};
class A {
B *obj;
public:
A(int value) : obj(new B(value)) {}
~A() { delete B; }
};
In such a case, however, chances are pretty good that A should just be written like:
class A {
B obj;
public:
A(int v) : obj(v) {}
};
int main() {
A a(3);
return 0;
}
This way, the instance of B will be created and destroyed automatically, without any intervention on your part at all.
Almost always A should manage it's members as this is what RAII is based off of. Use unique_ptr when you can.
If it doesn't manage it's data then it should use a different smart pointer, specifically shared_ptr. This shifts the responsibility to the shared_ptr, which is much less error prone than a vanilla pointer.
And of course, the preferred way is to use no pointers at all. Why are you calling new in the first place?
Related
Say that I have a class A and a class B which further has a subclass B1. Now I want to assign a pointer of B1 to be a member of A. I could do that by simply heap allocating B1 and then using delete in the destructor of A as follows:
class B {
public:
B() { };
};
class B1 : public B {
public:
B1() { };
};
class A {
public:
B* b_instance;
A(B* b_instance){
this->b_instance = b_instance;
};
~A(){
delete this->b_instance;
};
};
int main() {
B* b_instance = new B1();
A a_instance(b_instance);
return 0;
};
Now I believe another approach (and one that is more favored?) would use std::unique_ptr, whereby a unique_ptr to B1 is given to A and thus, as a smart pointer, whenever A is destroyed B1 is automatically destroyed as well since there are no more references to it. My best guess is that it should look something like this:
#include <memory>
class B {
public:
B() { };
};
class B1 : public B {
public:
B1() { };
};
class A {
public:
std::unique_ptr<B> b_instance;
A(B& b_instance){
this->b_instance = std::make_unique<B>(b_instance);
};
~A(){ };
};
int main() {
B1 b_instance;
A a_instance(b_instance);
return 0;
};
Is the unique_ptr approach the same as the approach outlined above so long as you remember to include delete this->b_instance in the destructor of A? Or are there other benefits of the unique_ptr approach?
Is the unique_ptr approach the same as the approach outlined above so long as you remember to include delete this->b_instance in the destructor of A?
More or less.
Or are there other benefits of the unique_ptr approach?
Yes, you get automatic move semantics and copy semantics is turned off, greatly helping to prevent involuntary multiple owners of the same resource.
I would like to ask the following:
Suppose that we have three classes in C++: A, B and C. An object of class A is creating and owning an object of class B. It is then giving the reference of B to an object of class C to be stored as a pointer variable. So, what is the best practice to inform C, that the pointer to B is no longer valid (and should be set to null), if A is deleted?
Is there a general approach or for example a Qt specific one?
Use std::weak_ptr
Example (live demo here)
class A
{
private:
std::shared_ptr<B> myB;
public:
A() :
myB(std::make_shared<B>())
{
}
std::weak_ptr<B> GetB()
{
return myB;
}
};
class B
{
};
class C
{
private:
std::weak_ptr<B> theB;
public:
C(std::weak_ptr<B> b) :
theB(b)
{
}
void test()
{
auto b = theB.lock();
if (b)
{
// theB is still valid
}
else
{
// theB is gone
}
}
};
I'm quite new to the concept of inheritance, and to C++ too, so my problem may be really stupid...
class A {
public :
A() {}
A(string name) {name_ = name}
private :
string name_;
}
class B : public A {
public :
B() {}
B(string name, int number) {
name_ = name;
number_ = number;
}
private :
string name;
int number;
}
class C {
public :
C() {}
void addClass(int id, A* a) {
map[id] = a;
}
private :
Hash_Map<int, A*> map;
}
void main() {
C* c = new C();
for (int i = 0; i < 10; i++) {
B* b = new B("randomName", 50);
c->addClass(i, b); //1st problem
delete b; //2nd problem
}
}
1st problem : shouldn't "map" in "c" keep the attribute "number" from the class "B"? I know I put A* in parameter, but if I had several class that derived from A, how should I do it?
2nd problem : All of my attributes in "map" seem to get random values when I delete "b". I'm guessing the problem is that I need to copy "b" into a new object, but how can I do it if I have "A*" as my addClass() parameter? My pointer b seems to be converted into its parent class
EDIT : had to change several things in my code that I forgot...
Bunch of problems:
1) No initializing members within a class declaration! (Your edit fixed this)
class B : public A {
public :
B() : name("A"), number(0) {} // initialize in constructor. that's what they are for!
private :
string name;
int number;
}
(Repeat that for A's declaration as well)
2)
You're storing a copy of the pointer to A (that was passed in as argument to addClass)in your map, not the actual object.
So, your map holds: 100 -> pointer to b
Then you delete whatever b points to. What would you think map[100] contains now?
A pointer to garbage! So, don't delete the pointer outside! Let C take care of it.
3) (My previous answer had a glaring error and someone voted it up. So, I'll keep the earlier part and point out my mistake)
Don't use pointers unless you need to. Save yourself some work. Go play the guitar or read some of Herb Sutter's articles!
void main() {
// don't use pointers and require that you delete them (unless you need to)
B b; // default constructor is called automatically. it is destroyed for you, by the compiler
// at the end of its scope (in this case, closing brace of main() )
C c;
c.addClass(100, b);
}
Let's fix C too. Can we get rid of those nasty pointers?
class C {
public :
C() {}
void addClass(const int id, const A a) { // use const, its a good habit!
map[id] = a;
}
private :
Hash_Map<int id, A a> map;
}
Now, what's wrong with this? Not just extra copies; when you pass b as argument to addClass by value, the compiler is gonna copy the A portion of b! So, we lostb`'s data (and overrides)!
So, we absolutely have to use pointers (references are dangerous, since they're deleted at scope exit).
What's important is that you make C owns the deletion.
So your code would now look like:
class C {
public :
C() {}
~C() {
for(pair<int, A*>& p : map) // C++11 syntax, yay!
delete p.second; // here's where you clean up. not in main.
}
void addClass(const int id, const A* a) {
map[id] = a;
}
private :
Hash_Map<int, A*> map;
}
void main() {
B* b = new B(); // back to square 1!
C c;
c.addClass(100, &b);
} // no memory leaks
But I hate taking care of deletion you say.. Fear not, we have shared_ptr!
#include <memory>
using namespace std;
typedef shared_ptr<A> Aptr;
class C {
public :
C() {}
~C() {
cout << "Drinking a beer coz i use shared_ptr";
}
void addClass(const int id, Aptr& a) {
map[id] = a;
}
private :
Hash_Map<int, Aptr> map;
}
void main() {
Aptr b(new B());
C c;
c.addClass(100, b);
} // still no memory leaks
Hope that helps.
I have wrote a program that use inheritance, everything is OK but an error that I think shouldn't not be here naturally.
here is my program:
class A
{
protected:
int x;
public:
A(){};
~A(){};
A* operator=(const A* other)
{
this->x = other->x;
return this;
}
};
class B : public A
{
public:
B() : A(){};
~B(){};
};
class C
{
protected:
A *a;
public:
C(const A* other){ *(this->a) = other; };
};
int main()
{
B *b = new B();
C *c = new C(b);
return 0;
}
It produces an execution time error in the statement 'this->x = other->x;'.
What about this?
*(this->a) is undefined behavior, because this->a wasn't initialized - it's just a dangling pointer.
You can use a = new A; *a = other (the this-> in this case is redundant), but this isn't the proper C++ way - you should use RAII (look it up) - you wouldn't need destructors, assignment operators or copy constructors if you did.
Also, operator = typically returns *this by reference.
I like Luchian's answer but there is still some places to enhanced in your code, you may still encounter some undefined behavior in your code before you fix other potential bugs.
class A
{
protected:
int x;
public:
A():x(0){} // should always initialize x in constructor
virtual ~A()=0 {} // as A is a base case, ~A must be virtual
A& operator=(const A& other) // a reference will be more practical better?
{
this->x = other.x;
return *this;
}
};
If you don't want to make B object as well which means B is serviced as a base class, you should make its destructor virtual as well, even make it pure virtual.
class B : public A
{
public:
B() : A(){}
virtual ~B(){} =0
{ }
};
*(this->a) = other; is answered by Luchian already. In your code, if you want to keep a copy of pointer which points to A, you can simply initialize a_ptr in member initialize list
see below demo code:
class C
{
protected:
A *a_ptr;
public:
C(A* other):a_ptr(other){ }
};
Finally come to your main function, if b,c are only used in main function, when program finishes, system will claim dynamic allocated memory back, but if you use a,b in a loop, you need to delete them manually.
In C++ I have a reference to an object that wants to point back to its owner, but I can't set the pointer during the containing class' construction because its not done constructing. So I'm trying to do something like this:
class A {
public:
A() : b(this) {}
private:
B b;
};
class B {
public:
B(A* _a) : a(_a) {}
private:
A* a;
};
Is there a way to ensure B always gets initialized with an A* without A holding a pointer to B?
Thanks
Try this:
class A;
class B {
public:
B(A *_a) : a(_a) {};
private:
A* a;
};
class A {
public:
A() : b(this) {};
private:
B b;
};
Since B is contained completely in A, it must be declared first. It needs a pointer to A, so you have to forward-declare A before you declare B.
This code compiles under more-or-less current versions of g++.
In C++ I have a reference to an object that wants to point back to its owner, but I can't set the pointer during the containing class' construction because its not done constructing.
You can store the pointer alright.
What you can't do is to try to get to the members/methods of A through the pointer in the constructor of B, since the parent instance might not be fully initialized at the point:
#include <iostream>
class Y;
class X
{
Y* y;
public:
X(Y* y);
};
class Y
{
X x;
int n;
public:
Y(): x(this), n(42) {}
int get_n() const { return n; }
};
X::X(Y* p): y(p)
{
//Now this is illegal:
//as it is, the n member has not been initialized yet for parent
//and hence get_n will return garbage
std::cout << p->get_n() << '\n';
}
int main()
{
Y y;
}
If you were to switch around the members in Y, so n would get initialized first, the constructor of X would print 42, but that is too fragile to depend on.