Based on my understanding C++ manages memory for me by cleaning it when variable becomes out of scope.
But how does it work when I use polymorphism and abstract classes, it looks like I have to manage it by my self.
Here is an exampl
I have class A and sub-class B
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
class A {
public:
virtual ~A() {
std::cout << "Destroy A";
}
virtualvoid sayHi()=0;
};
class B : public A {
public:
virtual ~B() {
std::cout << "Destroy B";
}
void sayHi() override {
std::cout << "Hi";
}
};
Now I have a function
1 2 3 4
void someFunction() {
A *a = new B();
a->sayHi();
}
The variable a must be a pointer as A is abstract. And because it is a pointer and dynamically allocates memory, the actual instance of B won't be cleared when function is done. And if this statement is correct it means that I always have to delete pointer manually.
void someFunction() {
B b ; // object with automatic storage duration
A& a = b ; // reference to A
a.sayHi();
A* pa = std::addressof(b) ; // raw (non-owning) pointer to A
pa->sayHi() ;
// object with dynamic storage duration
// the smart pointer automates the management of its life-time
// http://en.cppreference.com/w/cpp/memory/unique_ptr
// http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique
// pa2: smart (owning) pointer to A
std::unique_ptr<A> pa2 = std::make_unique<B>() ; // #incude <memory>
pa2->sayHi() ;
}
so basically to summarize I should avoid usage of "new" unless it is not a dynamic array.
So the next question, if I want "someFunction" to return the reference of A, how should I do it so I don't loose the actual object because of the scope of the function?
> use shared_ptr if more than one object wants to store the pointer.
Use shared_ptr if and only if the ownership of the object is shared.
It is perfectly acceptable to store raw non-owning pointers.
A shared_ptr represents shared ownership and can be very useful, even essential, but shared ownership isn’t my ideal, and it always carries a cost (independently of how you represent the sharing). It is better (simpler) if an object has a definite owner and a definite, predictable life span. - Stroustrup in 'The C++ Programming language'
ie. in general,
1. Strongly favour ordinary scoped objects to objects owned by unique_ptr
2. Strongly favour unique_ptr over shared_ptr. (shared_ptr should be the last resort.)
What is often talked about on the web is the run-time cost of using shared pointers; in most cases, the more important cost of using shared pointers is the (often needless) increase in the complexity of the design.
class Storage {
A *a;
public:
void store(A &a) {
this->a = &a;
}
A &getA() {
return *a;
}
};
void someFunction(Storage &storage) {
B b;
A &a = b;
storage.store(a);
}
int main() {
Storage storage{};
someFunction(storage);
A &a = storage.getA();
a.sayHi();
return 0;
}
So I added Storage class to store some value. It can be linked list or other time of collection. I must use pointer in storage class as A is abstract. "someFunction" just creates instance of B and stores it in the storage. When function is done, "a.sayHi" prints nothing, and I got following warning/error: "libc++abi.dylib: Pure virtual function called!". As I understand the actual object was destroyed and Storage has link to a corrupted memory. There are two questions:
1. How do I make sure that the object is still there after "someFunction" is done
2. Who manages the memory in Storage class? When some other code decides to store new "a" to a storage, do I have to call "delete"? What if this object is used in other places?
But in this case it is a huge pain to use polymorphism in C++. I have to use pointers because of polymorphism.
If I store object in Storage and exit the "someFunction". The pointer in storage still should have instance of original object, as it is storage. But here it will point to some garbage as object is out of scope, and the only way to solve this , that I am aware of, is to pass by value that won't be efficient as I want to save classes and structures.
Now when object is deleted from storage I don't want to delete it from everywhere else as it is just a storage and somebody may have the reference they need.
Probably I just want to have Garbage collector.
What are strategies to manage memory in such usecase?
> What are strategies to manage memory in such usecase?
Repeat:
For unique ownership, use std::unique_ptr (object is destroyed when it becomes ownerless).
For shared ownership, use std::shared_ptr (object is destroyed when its last owner goes away).
"Now when object is deleted from storage I don't want to delete it from everywhere else as it is just a storage and somebody may have the reference they need." - this would imply that the ownership is shared.