2

I'm running VC++ 2005 so std::unique_ptr is not available AFAIK. I use some library functions (black box) which effectively do return new T[n] and I want to wrap the result in some object which will mean I don't have to delete them in my destructor.

Does anything exist in the standard libraries circa VC++ 2008? If not, would the boost version of unique_ptr work perfectly as in this answer?

To clarify some confusion in the comments, the library function returns a raw pointer to a dynamically allocated array and I don't have access to change that... I need to take that pointer and wrap it in an object which automatically calls delete [] when the object goes out of scope.

Community
  • 1
  • 1
Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • Consider using `std::vector`. – hmjd Jul 17 '12 at 08:45
  • Does it have a ctor which takes in a pointer to pre-allocated memory? http://www.cplusplus.com/reference/stl/vector/vector/ If you can provide a working example the answer is yours :) – Mr. Boy Jul 17 '12 at 08:48
  • you can give it an initial size and it is a contiguous block of memory. What is the type of `T` ? – hmjd Jul 17 '12 at 08:49
  • @hmjd: it does not work with pre-allocated memory though, so not really an option unless you can modify the library itself. – Matthieu M. Jul 17 '12 at 08:54
  • In VC++ 2008 (I think SP1 is needed) you have [TR1](http://en.wikipedia.org/wiki/C%2B%2B_Technical_Report_1), so you have shared_ptr, but not unique_ptr. It can do the trick, but it can also be dangerous, if the pointers are not meant to be shared. – MikMik Jul 17 '12 at 09:04
  • @John, I also misread the question. I thought you had control of the library functions. – hmjd Jul 17 '12 at 09:04
  • Why dont you roll your own unique_ptr like class, it shouldnt be difficult, something like: template struct CSmartArrayDeleter { T* t; ~CSmartArrayDeleter(){ delete[] t; } void Set(T* p) { t = p; }}; With some additional null pointer checking. – marcinj Jul 17 '12 at 09:21
  • 1
    @luskan - because the whole point of STL/boost is we don't keep making our own versions of everything. – Mr. Boy Jul 17 '12 at 09:24
  • @luskan: Because it's easy to forget important details, like inhibiting the default copy constructor and copy-assignment operator, and remembering to delete the previous object on assignment. – Mike Seymour Jul 17 '12 at 09:27
  • I agree, I am also stuck in VS2005 world, and I am not even allowed to use boost or any external libs. – marcinj Jul 17 '12 at 09:28
  • http://stackoverflow.com/questions/1044785/c-auto-ptr-for-arrays - show a solution with vector, but to me it looks more scary than rolling your own solution – marcinj Jul 17 '12 at 09:33
  • @luskan I'm still awaiting a response if boost is allowed :) – Mr. Boy Jul 17 '12 at 10:44

2 Answers2

0

In the pre-2011 standard library, all you've got is auto_ptr, which is suitable for returning from functions. However, it only works with single objects, not arrays, so it's not suitable for this use.

As far as I can tell, there isn't a unique_ptr in Boost. There is a scoped_ptr and scoped_array, but they aren't transferable and so can't be returned from a function.

boost::shared_array might be suitable, although it uses reference counting and so has a (hopefully small) overhead compared to a single-ownership pointer.

std::vector might be a good choice; as long as your compiler supports "return value optimisation" then you can (with a little bit of care) return one from a function without any unnecessary memory allocation or copying. However, it has the disadvantage that it doesn't prevent accidental copying of the data.

UPDATE: I've just noticed the words "black box" in your question, which I think might imply that the library functions return raw pointers, and you want to assign them to a smart pointer that will destroy them with delete [], and can't modify the functions themselves. If that's the case, boost::scoped_array should do the trick, and apologies to the people who deleted their answers in response to my comments.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • `std::vector` is only suitable if you can change the library itself, I am not sure this is the OP's case here. – Matthieu M. Jul 17 '12 at 08:55
  • @MatthieuM.: Yes, I just noticed that I misread the question. I thought he wanted to return a smart pointer, not deal with a returned raw pointer. – Mike Seymour Jul 17 '12 at 08:56
  • `boost::unique_ptr` appears to exist (http://www.boost.org/doc/libs/1_37_0/doc/html/boost/interprocess/unique_ptr.html) but whether it's the same as modern `std::unique_ptr` I don't know. However if we're using boost, it looks like `boost::scoped_array` is even nicer for a class member variable which wraps an array needing deletion on class destruction. – Mr. Boy Jul 17 '12 at 09:10
  • 2
    @John: `boost::interprocess::unique_ptr` is intended for sharing memory between processes (being in the `interprocess` namespace). I don't know whether it's suitable for managing normal memory, and it looks like you'd have to provide your own deleter to deal with arrays, unlike `std::unique_ptr` which is specialised for arrays. `scoped_array` sounds more suitable, especially if you don't need to transfer ownership. – Mike Seymour Jul 17 '12 at 09:25
0

It depends what you want to do with the resulting value.

In general, I would advise boost::scoped_ptr and boost::scoped_array in C++03. However note that they were crafted with a very specific mindset: to limit the scope of the resource. That is, they go further than just handling cleanup, they also guarantee that the resource will not leave the scope, ie cannot be transferred to the caller.

If you want more, it's not easy in C++03 (because of the absence of movable types). In this case, you might need to craft an "extended" boost::scoped_ptr, adding a release method for example to allow passing memory to the caller (which is then expecting to be taking care of it properly).

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722