2

I'm looking for a way to automatically deallocate an array of wchar_ts – kind of like an autopointer (I'm not really aquainted with std::auto_ptr, but I think it cannot be used for arrays).

The code I have right now is this:

/* volume is of type wstring,
 * hr is of type HRESULT, 
 * VSS_PWSZ equals wchar_t* 
 */

VSS_PWSZ pwszVolume = new wchar_t[volume.size() + 1];
std::copy(volume.begin(), volume.end(), &pwszVolume);
pwszVolume[volume.size()] = 0;

hr = pDiffMgmt->QueryDiffAreasOnVolume(pwszVolume, &pEnumMgmt);

delete[] pwszVolume;
pwszVolume = NULL;

I don't really get why this stupid function cannot take a const wchar_t*, otherwise I could just pass volume.c_str().

So far so good, I think my code solves this problem, but now the memory management is getting more complicated: I would have to duplicate the delete[] code to account for exceptions which might be thrown (and which I do not want to catch at this point.)

Is there a way I can get pwszVolume to be deallocated automatically when the current scope is left?

Felix Dombek
  • 13,664
  • 17
  • 79
  • 131

5 Answers5

6

Use std::vector<wchar_t> it is your basic C++ array (or std::wstring if you want to manipulate it like a string).

std::vector<wchar_t> pwszVolume(volume.begin(), volume.end());
pwszVolume.push_back(0);

hr = pDiffMgmt->QueryDiffAreasOnVolume(&pwszVolume[0], &pEnumMgmt);

The question may be. What does QueryDiffAreasOnVolume() do with the data?
Maybe you do not need to copy it out.

Martin York
  • 257,169
  • 86
  • 333
  • 562
  • If that function never actually writes to the array in its first argument, you could cast away const-ness. If you're very, very, very sure. – Matt K Jul 26 '11 at 14:38
  • 4
    You can construct a `vector` from a range directly, no need for `std::copy`. Use `std::vector pwszVolume(volume.begin(), volume.end()); pwszVolume.push_back(0);`. – Frerich Raabe Jul 26 '11 at 14:41
  • `wstring` doesn't help me, but thanks for this `vector` code. (The code with `push_back` instead of `copy` can be slower if it just hits a boundary where a `resize` must occur on the vector, but I'm still going for this because of the conciseness.) – Felix Dombek Jul 26 '11 at 14:56
  • @Felix Dombek: What is the type of volume? We may not need to push the '0' if it is already a string with the trailing '\0' – Martin York Jul 26 '11 at 17:38
  • @Martin: `volume` is a `wstring` so I guess I can indeed assume that the trailing NUL char is copied automatically. – Felix Dombek Jul 26 '11 at 18:35
  • 1
    @Felix Dombek: Unfortunately not. Unless you explicitly added a '\0' into the string then the terminating '\0' is not part of the length and only technically appears with a call to c_str(). But I believe in the new standard has data() returns a pointer to an area that is '\0' terminated. So you may be able to do this: `newV(&v.data[0], &v.data[v.size() + 1])` but I would validate that before taking my word. – Martin York Jul 26 '11 at 19:04
4

std::unique_ptr can be used with arrays as follows:

std::unique_ptr<wchar_t[]> pwszVolume(new wchar_t[volume.size() + 1]);

Another option is std::array.

But I agree with Martin's answer that you should just use an std::vector unless you really cannot afford to have the couple of extra pointers that the vector class holds.

Community
  • 1
  • 1
Praetorian
  • 106,671
  • 19
  • 240
  • 328
1

As others have said, std::vector is the preferred solution, by far. Otherwise (if e.g. you originally get the pointer from third party software which you cannot modify), there's boost::scoped_array or boost::shared_array.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

You can wrap wchar_t* inside a class, deallocate memory on destruct-or and you have an object that will be automatically deallocated when it loses scope.

xpda
  • 15,585
  • 8
  • 51
  • 82
cprogrammer
  • 5,503
  • 3
  • 36
  • 56
0

If you don't want the overhead from std::vector, use boost::array. It is your basic C++ array with static size.

TravisG
  • 2,373
  • 2
  • 30
  • 47
  • Or there is [std::tr1::array](http://msdn.microsoft.com/en-us/library/bb983093.aspx) if boost is not an option – Praetorian Jul 26 '11 at 14:41
  • 2
    What overhead? see http://stackoverflow.com/q/3664272/14065 But I generally agree that std:array or boost::array is a good alternative. – Martin York Jul 26 '11 at 14:42
  • @Martin: That link you show is a comparison between dynamically allocated arrays. The tr1 array is not dynamically allocated. Surely there is an overhead in dynamic allocation. – Benjamin Lindley Jul 26 '11 at 14:50
  • @Benjamin Lindley: I was not aware of that. I am still not fully familiar with the new standard. But that's interesting, why would I use a std::array over a normal language array? – Martin York Jul 26 '11 at 17:36
  • 1
    @Martin: A few reasons. It avoids bugs associated with pointer decay. It has convenience functions like `begin` and `end`, as well as things that are harder to do with pointers like `rbegin` and `rend`. Bounds checking with `at()`, etc... – Benjamin Lindley Jul 26 '11 at 17:47