1
\$\begingroup\$

The following class is a sort of "smart pointer" that can be used for automatically releasing pointers:

template <class Type>
class Releaser {
 public:
 Releaser(std::function<void(Type *)> function = [](Type *value) {
 value->Release();
 });
 ~Releaser();
 Type *operator->();
 Type &operator*();
 Type *get();
 Type **fill();
 private:
 Type *value_ = nullptr;
 std::function<void(Type *)> function_;
};
template <class Type>
Releaser<Type>::Releaser(std::function<void(Type *)> function)
 : function_(function) {}
template <class Type>
Releaser<Type>::~Releaser() {
 if (value_) function_(value_);
}
template <class Type>
Type *Releaser<Type>::operator->() {
 return value_;
}
template <class Type>
Type &Releaser<Type>::operator*() {
 return *value_;
}
template <class Type>
Type *Releaser<Type>::get() {
 return value_;
}
template <class Type>
Type **Releaser<Type>::fill() {
 return &value_;
}

It can be used for example like this:

Releaser<IMFAttributes> attributes;
auto status = MFCreateAttributes(attributes.fill(), 1);

where MFCreateAttributes has the following signature:

MFCreateAttributes(IMFAttributes** ppMFAttributes, unsigned int cInitialSize);

Do you see any way to improve this (e.g by getting rid of the std::function), or make it safer?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Sep 23, 2016 at 9:09
\$\endgroup\$
2
  • \$\begingroup\$ unique_ptr supports custom deleters. Though the deleter type will leak into the template arguments (which can be alleviated using a typedef). \$\endgroup\$ Commented Sep 23, 2016 at 10:51
  • \$\begingroup\$ unique_ptr doesn't work because of the missing "fill" functionality. See stackoverflow.com/questions/12403750/… \$\endgroup\$ Commented Sep 23, 2016 at 11:48

1 Answer 1

4
\$\begingroup\$

unique_ptr has capability for custom deleters.

Besides that assuming you are doing this to deal with COM objects then you can use ComPtr and its GetAddressOf


If you define a destructor you should also define (or disallow in this case) the copy construct and copy assign. Failure to do so will result in dangling pointers and double frees:

Releaser<IMFAttributes> attributes;
auto status = MFCreateAttributes(attributes.fill(), 1);
{
 Releaser<IMFAttributes> att = attributes;
} // att gets cleaned up
//attributes contains a dangling pointer
answered Sep 23, 2016 at 12:48
\$\endgroup\$
1
  • \$\begingroup\$ Thenks, very useful input! unique_ptr doesn't work because of the missing GetAddressOf function. I didn't know ComPtr, but this works quite well for cases where only a simple Release is needed, however not for custom release functions (for example if value_->Shutdown() has to be called instead of value_->Release()). Preventing a copy constructor is a very good point though. Also, I ended up adding an assert(value != nullptr) in the fill function, to avoid overriding a non-released pointer. \$\endgroup\$ Commented Sep 23, 2016 at 13:02

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.