Reputation: 51
I implemented a C-API for a C++ class which uses shared-pointers of other objects to access them. In my C-API I can of course only get raw pointers. So I "convert" the raw pointer in my C-API to a shared-pointer and use this then with my C++ class methods:
method(std::shared_ptr<dataType>(raw-pointer));
Now I have the problem that at the end of "method" always the shared-pointer destructor is called and it unfortunately kills the object my raw-pointer is pointing at (which I don't want). So, how can I prevent the raw-pointer from being killed?
I already tried shared-pointer functions like reset() or swap(), but they all didn't let my raw-pointer go...
bool Traffic_doStep(traffic_handle t, environment_handle e, double cycletime) {
if (!valid(t, __FUNCTION__)) return false;
if (!valid(e, __FUNCTION__)) return false;
if (!valid(cycletime, __FUNCTION__)) return false;
try {
t->doStep(std::shared_ptr<Environment>(e), cycletime);
return true;
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return false;
}
}
Expected result would be that the raw-pointer e is still pointing to a valid object after this function returned. Actually the raw-pointer points then to a deleted object.
Upvotes: 4
Views: 2709
Reputation: 747
You may provide a custom deleter of a shared pointer.
Here is a viable constructor:
template< class Y, class Deleter >
shared_ptr( Y* ptr, Deleter d );
But I would rather use a unique pointer and then release it.
Upvotes: 2
Reputation: 20396
std::shared_ptr
The purpose of Smart Pointers in C++ is to provide automatic Lifetime management. When you write std::shared_ptr<int> ptr{raw_ptr};
, the expectation is that when ptr
goes out of scope, the object pointed to by raw_ptr
will be delete
'd. If this is not the intent, then you should not be placing the pointer in a smart pointer.
So if your application does not manage the lifetime of a pointer, then it is perfectly acceptable to store a raw pointer.
If the API behind the function cannot be altered, you will instead need to construct the std::shared_ptr
with a no-op deleter function, so that when clean-up is called, nothing will happen to the pointer.
try {
std::shared_ptr<Environment> temp_ptr{e, [](int *) {}/*No-Op Deleter*/};
t->doStep(temp_ptr, cycletime);
return true;
}
This will solve your problem, but this is, of course, an Antipattern; don't do this unless you've been forced to by API design constraints that you cannot control.
Upvotes: 15