Reputation: 7388
I provide two ways to add elements to my collection, once per const reference and once per pointer.
void push_back(const value_type *val) {
element *elem = new element(val);
//...
}
void push_back(const value_type &val) {
push_back(&val);
}
The element
class holds the value as a pointer.
class element {
private:
const value_type *value;
public:
element(const value_type *value):
value(value) {
}
~element() {
delete value;
}
Obviously when elements are popped or the collection is deleted, the memory has to be freed if elements were added as a pointer. However, this yields an error when the elements were not manually allocated and passed by reference.
Is there any other option to solve this issue than additionally storing if the element is dynamically allocated on push_back time?
Upvotes: 0
Views: 110
Reputation: 3918
It's a flawed design in general. And there are different ways you can change your design to achieve what you need. Mark's answer is a straightforward way to go about it, for example.
That being said, here is a possible solution using your design. Once again, I do not recommend it as it relies on internals of how compilers build stack, and is not portable across compilers/platforms.
Basically, in ~element()
you can check if the address stored in value
is on stack or on heap by comparing it to the current stack pointer. If the address stored in value
is higher than the stack pointer then it's on stack and should not be deleted (provided usual location of the stack at top of address space). If it's less than stack pointer - it's on heap.
Code to illustrate the relations of the addresses (GCC, x64 linux):
#include <iostream>
int main()
{
int * heap_(new int(0));
int stack_(0);
void * rsp_(nullptr);
asm("mov %%rsp, %0" : "=m" (rsp_));
std::cout << "heap address\t: " << heap_
<< "\nstack address\t: " << &stack_
<< "\nstack pointer\t: " << rsp_ << std::endl;
delete (heap_);
return (0);
}
Program output:
heap address : 0xc52010
stack address : 0x7fff528ffee4
stack pointer : 0x7fff528ffee0
ideone.com gives access to GCC, but uses x86 version - esp
register instead of rsp
. The code has to be changed (non-portability).
Upvotes: 1
Reputation: 308186
Just be consistent and always store a pointer that can be deleted.
void push_back(const value_type &val) {
push_back(new value_type(val));
}
Upvotes: 1