Before focusing on the dynamics of contructing / destructing / copy (and possible optimization), there is a consideration that you do not seem to know about: values ββare not polymorphic .
If B comes from A ,
B b; A a(b);
will not make A copy of B It just copies the subcomponent B A into A
Unlike values, pointer and links are polymorphic :
B b; B* pb = &b; A* pa = pb; B* pb2 = const_cast<B*>(pa);
actually lead to pa pointing to b a subcomponent of b A, but pb and pb2 to point to the same B
So a vector<A> contains A values , therefore
vecotr<A> v; v.push_back(B());
will result in:
- Create an empty
v ; - Create a temporary B ();
- Make v large enough to contain A
- Create in v.end () a Copied from temporary subcomponent B A.
- Destroy Temporary B
And - at the end of the function
- destroy v (and thereby destroy A inside it)
Now the memory is clear.
When using pointers:
vector<A*> v; v.push_back(new B());
will result in:
- Create empty
v - Create B on the heap
- Increase v to contain A *
- Convert address B to its subcomponent address (for single inheritance, they are likely to be the same)
- Create in v.end () a *, copied from B to the converted address (note that you are converting pointers, not objects).
- Destroy v
- Destroy A * in it.
- There is still a heap (memory leak, since there is no other way to access it to delete it)
To avoid leakage, you should:
- Create B on the stack and get its address or ...
- Use
std::unique_ptr<A> instead of A* in the vector (so when you destroy the vector, unique_ptr is destroyed, and its destructor destroys the selected Sub object, which has a virtual destructor, will destroy B.
A more efficient demonstration on the above question can be asked with the following code:
// Compile as g++ -pedantic -Wall -std=c++11
It will be displayed as
creating some objects - creating A at 0x22febc - creating A at 0x22feb8 - creating A at 0x22feb4 - creating B at 0x22feb4 - creating A at 0x22feb0 - creating B at 0x22feb0 - creating A at 0x22feac - creating C at 0x22feac - creating A at 0x22fea8 - creating C at 0x22fea8 operating with values - creating A at 0x3e3eb8 from 0x22febc - creating A at 0x3e2434 from 0x22febc - creating A at 0x3e2430 from 0x3e3eb8 - destroying A at 0x3e3eb8 - creating A at 0x3e2448 from 0x22feb4 - creating A at 0x3e2440 from 0x3e2430 - creating A at 0x3e2444 from 0x3e2434 - destroying A at 0x3e2430 - destroying A at 0x3e2434 - creating A at 0x3e244c from 0x22feb4 - creating A at 0x3e2468 from 0x22feac - creating A at 0x3e2458 from 0x3e2440 - creating A at 0x3e245c from 0x3e2444 - creating A at 0x3e2460 from 0x3e2448 - creating A at 0x3e2464 from 0x3e244c - destroying A at 0x3e2440 - destroying A at 0x3e2444 - destroying A at 0x3e2448 - destroying A at 0x3e244c - creating A at 0x3e246c from 0x22feac - creating A at 0x3e2470 from 0x22feb8 - creating A at 0x3e2474 from 0x22feb8 - creating A at 0x3e24a0 from 0x22feb0 - creating A at 0x3e2480 from 0x3e2458 - creating A at 0x3e2484 from 0x3e245c - creating A at 0x3e2488 from 0x3e2460 - creating A at 0x3e248c from 0x3e2464 - creating A at 0x3e2490 from 0x3e2468 - creating A at 0x3e2494 from 0x3e246c - creating A at 0x3e2498 from 0x3e2470 - creating A at 0x3e249c from 0x3e2474 - destroying A at 0x3e2458 - destroying A at 0x3e245c - destroying A at 0x3e2460 - destroying A at 0x3e2464 - destroying A at 0x3e2468 - destroying A at 0x3e246c - destroying A at 0x3e2470 - destroying A at 0x3e2474 - creating A at 0x3e24a4 from 0x22feb0 - creating A at 0x3e24a8 from 0x22fea8 - creating A at 0x3e24ac from 0x22fea8 - A hello from 0x3e2480 - A hello from 0x3e2484 - A hello from 0x3e2488 - A hello from 0x3e248c - A hello from 0x3e2490 - A hello from 0x3e2494 - A hello from 0x3e2498 - A hello from 0x3e249c - A hello from 0x3e24a0 - A hello from 0x3e24a4 - A hello from 0x3e24a8 - A hello from 0x3e24ac at '}' destroy the value vector - destroying A at 0x3e2480 - destroying A at 0x3e2484 - destroying A at 0x3e2488 - destroying A at 0x3e248c - destroying A at 0x3e2490 - destroying A at 0x3e2494 - destroying A at 0x3e2498 - destroying A at 0x3e249c - destroying A at 0x3e24a0 - destroying A at 0x3e24a4 - destroying A at 0x3e24a8 - destroying A at 0x3e24ac operating with pointers - A hello from 0x22febc - A hello from 0x22febc - B hello from 0x22feb4 - B hello from 0x22feb4 - C hello from 0x22feac - C hello from 0x22feac - A hello from 0x22feb8 - A hello from 0x22feb8 - B hello from 0x22feb0 - B hello from 0x22feb0 - C hello from 0x22fea8 - C hello from 0x22fea8 at '}' destroy the pointer vector operating with list of values - creating A at 0x3e2448 from 0x22febc - creating A at 0x3e24d0 from 0x22febc - creating A at 0x3e24e8 from 0x22feb4 - creating A at 0x3e2500 from 0x22feb4 - creating A at 0x3e2518 from 0x22feac - creating A at 0x3e2530 from 0x22feac - creating A at 0x3e2548 from 0x22feb8 - creating A at 0x3e2560 from 0x22feb8 - creating A at 0x3e2578 from 0x22feb0 - creating A at 0x3e2590 from 0x22feb0 - creating A at 0x3e25a8 from 0x22fea8 - creating A at 0x3e25c0 from 0x22fea8 - A hello from 0x3e2448 - A hello from 0x3e24d0 - A hello from 0x3e24e8 - A hello from 0x3e2500 - A hello from 0x3e2518 - A hello from 0x3e2530 - A hello from 0x3e2548 - A hello from 0x3e2560 - A hello from 0x3e2578 - A hello from 0x3e2590 - A hello from 0x3e25a8 - A hello from 0x3e25c0 at '}' destroy the value list - destroying A at 0x3e2448 - destroying A at 0x3e24d0 - destroying A at 0x3e24e8 - destroying A at 0x3e2500 - destroying A at 0x3e2518 - destroying A at 0x3e2530 - destroying A at 0x3e2548 - destroying A at 0x3e2560 - destroying A at 0x3e2578 - destroying A at 0x3e2590 - destroying A at 0x3e25a8 - destroying A at 0x3e25c0 operating with list of pointers - A hello from 0x22febc - A hello from 0x22febc - B hello from 0x22feb4 - B hello from 0x22feb4 - C hello from 0x22feac - C hello from 0x22feac - A hello from 0x22feb8 - A hello from 0x22feb8 - B hello from 0x22feb0 - B hello from 0x22feb0 - C hello from 0x22fea8 - C hello from 0x22fea8 at '}' destroy the pointer list now finally at '};' destroy the objects created at the beginning - destroying C at 0x22fea8 - destroying A at 0x22fea8 - destroying C at 0x22feac - destroying A at 0x22feac - destroying B at 0x22feb0 - destroying A at 0x22feb0 - destroying B at 0x22feb4 - destroying A at 0x22feb4 - destroying A at 0x22feb8 - destroying A at 0x22febc
source share