I know that the go-to rule is to always use shared_ptr
s or other smart pointers. However, I'm not sure how exactly to implement it without copy ctor'ing with std::make_shared
. I'll elaborate:
The problem
I want to create a tree-like expression, like:
struct foo{
std::vector<foo*> v;
};
This allows me to do the following:
foo add(foo& f1, foo& f2){
return foo {&f1, &f2};
}
That's good, because then the two will become children of a new node.
I want the following to be evaluated correctly:
foo x, y;
auto z = add(x,y);
assert(z.v[0] == &x && z.v[1] == &y);
This way, there's no copying and it's all good. However, we have a resource management issue here.
Addressing the resource management issue
If these elements are allocated on the heap, and someone unknowingly might, then we'll run into a memory leak. So the best way to do this is to use smart pointers for RAII:
struct foo{
std::vector<std::shared_ptr<foo> > v;
};
foo add(foo& f1, foo& f2){
return foo {std::make_shared<foo>(f1), std::make_shared<foo>(f2)};
}
This is good, but we're calling the copy ctor of f1 and f2 here. Suppose copying takes a long time and we don't want to incur that cost.
We definitely, cannot do:
foo add(foo& f1, foo& f2){
return foo {std::shared_ptr<foo>(&f1), std::shared_ptr<foo>(&f2)};
}
because whenever we remove z
in z = x+y
, we will call delete
on each of x
and y
, which could be allocated on the stack. And we definitely do not want to delete
things on the stack.
So what should I do in this case?
Let me know if I should supply more information on the context.