In short, I am wondering if there is an auto_ptr like type for arrays. I know I could roll my own, I'm just making sure that there isn't already something out there.
I know about vectors as well. however I don't think I can use them. I am using several of the Windows APIs/SDKs such as the Windows Media SDK, Direct Show API which in order to get back some structures to call a function which takes a pointer and a size twice. The first time passing NULL as the pointer to get back the size of the structure that I have to allocated in order to receive the data I am looking for. For example:
CComQIPtr<IWMMediaProps> pProps(m_pStreamConfig);
DWORD cbType = 0;
WM_MEDIA_TYPE *pType = NULL;
hr = pProps->GetMediaType(NULL, &cbType);
CHECK_HR(hr);
pType = (WM_MEDIA_TYPE*)new BYTE[cbType]; // Would like to use auto_ptr instread
hr = pProps->GetMediaType(pType, &cbType);
CHECK_HR(hr);
// ... do some stuff
delete[] pType;
Since cbType typically comes back bigger than sizeof(WM_MEDIA_TYPE) due to the fact is has a pointer to another structure in it, I can't just allocate WM_MEDIA_TYPE objects. Is there anything like this out there?
Use
std::vector<BYTE> buffer(cbType);
pType = (WM_MEDIA_TYPE*)&buffer[0];
or since C++11
std::vector<BYTE> buffer(cbType);
pType = (WM_MEDIA_TYPE*)buffer.data();
instead.
Additional:
If someone is asking if the Vectors are guaranteed to be contiguous the answer is Yes since C++ 03 standard. There is another thread that already discussed it.
If C++11 is supported by your compiler, unique_ptr can be used for arrays.
unique_ptr<BYTE[]> buffer(new BYTE[cbType]);
pType = (WM_MEDIA_TYPE*)buffer.get();
boost scoped_array or you can use boost scoped_ptr with a custom deleter
There is nothing for this in the current std library. However, the future standard C++0x has an unique_ptr, which comes in replacement of auto_ptr, and which works with arrays.
A first implementation can be found here:
unique_ptr
Not in STL. Boost has some smart pointers with a similar idea. Check out scoped_array and shared_array
Related
The most satisfying part of writing a DIY memory manager is structuring it so you can forget about [delete] (e.g. by bundling everything into a singly allocated/deallocated buffer).
The way DirectX handles object creation means that you can't simply cast void memory into the types you want to make (can you?) and you have to rely on COM (+ remembering to [Release] local memory in every destructor) instead. Is there any way to subvert this and convince DirectX to use my pointers?
Instead of:
ID3D12Thing* thng = DirectX::CreateThing();
...
thng->Release();
thng = nullptr;
I want:
ID3D12Thing* thng = DirectX::CreateThingAt(Allocator->AlignedAlloc(sizeof(ID3D12Thing));
...
[memory emptied during shutdown]
Edit: This answer has been superseded by Chuck Walbourn's parallel answer.
While my answer is not completely wrong, after some investigation I'm pretty sure Chuck Walbourn's suggestion to use Microsoft::WRL::ComPtr is the better choice (Please see also comment section under C.B.'s answer for reasons). /Edit
To my knowledge it is not possible to plant external memory on Direct X structures, since they are all created by Direct X itself.
Nevertheless, if the main goal is maintenance and safety, it is possible to define a std::unique_ptr with a custom deleter which does the job of releasing.
struct DxDeleter {
void operator() (IUnknown* _moribund) { if(_moribund) _moribund->Release(); }
};
typedef std::unique_ptr<ID3D11Buffer,DxDeleter> dx_buffer_ptr;
typedef std::unique_ptr<ID3D11ShaderResourceView,DxDeleter> dx_resource_ptr;
typedef std::unique_ptr<ID3D11UnorderedAccessView,DxDeleter> dx_access_ptr;
...
The pointers then are simply assigned with e.g. myUniqueDxBufferPtr.reset( myRawBufferPtr ) or similar.
This has the high benefit, that releases don't need to be tracked. It is a good way not only for Direct X, but for all kinds of external libraries, which need allocation and deallocation (for example, I use the same technique also for Freeimage and ffmpeg).
It is also possible to define std::shared_ptrs for resources, which are shared by multiple items (e.g. you could keep your device alive as long as any buffers exist). But this is to handle with care - in opposite of std::unique_ptr, std::shared_ptrs don't have the deleter as a template parameter, but as a ctor parameter - which makes it terribly easy to erroneously assign something with a missing deleter (leaks).
void g_dxDelete( IUnknown* _moribund ) {
if( _moribund )
_moribund->Release();
}
typedef std::shared_ptr<ID3D11Device> dx_device_shared;
inline dx_device_shared assignDevice( ID3D11Device* _device ) {
return std::move( dx_device_shared( _device, g_dxDelete ) );
}
In that case you'd have to always be sure to assign the created device with dx_device_shared myDevice = assignDevice(myRawDevicePtr), but NEVER with dx_device_shared myDevice = myRawDevicePtr.
TL;DR: Use a smart-pointer like ComPtr.
I'm a big fan of std::unique_ptr and std::shared_ptr, but neither of them really correctly handle COM objects such as Direct3D interfaces which have their own built-in reference counts. A better choice is to use WRL class Microsoft::WRL::ComPtr or the C++/WinRT class winrt::com_ptr.
Some older coders might suggest the old ATL CComPtr, but the more modern Microsoft::WRL::ComPtr is a better choice.
Microsoft recently released a new library (WIL) for modern C++. It includes a new com pointer type:
wil::com_ptr<ID3D12Thing> thng{DirectX::CreateThing())};
I'm trying to put interface pointers to different types of shaders in a vector like this:
std::vector<ID3D11DeviceChild*> shaders;
ID3D11VertexShader* VS;
// ... instantiate and init VS
shaders.push_back(static_cast<ID3D11DeviceChild*>(VS));
// and when VS is needed again:
ID3D11VertexShader* VS = static_cast<ID3D11VertexShader*>(shaders[i]);
// use VS here
My question is whether this method for type casting COM interfaces is safe. I know it would work for normal polymorphic class hierarchies, but I'm not sure about COM.
First, I'd suggest storing smart pointers instead of raw owning pointers inside an STL container like std::vector, e.g.
std::vector<CComPtr<ID3D11DeviceChild>> shaders;
Using raw owning pointers inside STL containers is a source of leaks, potential bugs and exception unsafe code (observing raw pointers are fine, though).
To downcast from ID3D11DeviceChild* to ID3D11VertexShader*, consider using QueryInterface() (again, using ATL smart pointers like CComPtr simplifies the code):
CComPtr<ID3D11VertexShader> spVertexShader;
HRESULT hr = (shaders[i])->QueryInterface(IID_PPV_ARGS(&spVertexShader));
if (FAILED(hr))
...
PS
Unless I'm missing something, since ID3D11VertexShader is a derived class of ID3D11DeviceChild, you don't need the static_cast here:
shaders.push_back(static_cast<ID3D11DeviceChild*>(VS));
This should be fine:
shaders.push_back(VS);
Note on CAdapt
Note that you may need to use CAdapt with std::vector:
std::vector<CAdapt<CComPtr<ID3D11DeviceChild>>> shaders;
A conformant C++11 STL implementation should not require CAdapt, but I think it's necessary at least with VS2008 and VS2010.
I'm not sure about more modern versions of Visual Studio, but it seems they fixed that, e.g.:
you may want to read the paragraph titled "Resistance to overloaded address-of operators" in this Visual C++ blog post.
ID3D11VertexShader inherits from ID3D11DeviceChild so you don't even need to use static_cast<ID3D11DeviceChild*> to push them to vector. The safer way to downcast vector elements to shader is to use QueryInterface:
CComPtr<ID3D11VertexShader> vs;
if (S_OK == shaders[i]->QueryInterface(IID_ID3D11VertexShader,
reinterpret_cast<void**>(&vs)))
{
// Use vs here
}
It is safe for as long as you're absolutely sure the vector only contains ID3D11VertexShader, in which case you should just use it instead of ID3D11DeviceChild.
If you intend the vector to contain a mix of interface pointers, each with the common ancestor ID3D11DeviceChild, you're better off relying on QueryInterface, both for storing into and retrieving from the vector.
Remember, correct code is better than fast code, at least to begin with.
When you profile, if, and only if, you find out that QI is a bottleneck, then you should do something about it, but I recommend you use a vector of structs which has a pointer to a ID3D11DeviceChild and an interface identifier (IID) so you can inspect at runtime which kind of interface pointer you stored:
struct DeviceChildPtr {
ID3D11DeviceChild *ptr;
REFIID riid;
};
std::vector<DeviceChildPtr> shaders;
// ... instantiate, initialize ...
DeviceChildPtr shader;
shader.ptr = static_cast<ID3D11DeviceChild*>(VS);
shader.iid = IID_ID3D11VertexShader;
shaders.push_back(static_cast<ID3D11DeviceChild*>(shader));
// ...
DeviceChildPtr shader = shaders[i];
// If you only ever use global IIDs, you may replace IsEqualIID with ==
// This is like a half-baked QueryInterface that only checks for a specific IID
if (IsEqualIID(shader.riid, IID_ID3D11VertexShader) {
ID3D11VertexShader* VS = static_cast<ID3D11VertexShader*>(shader.ptr);
// ... use ...
}
If you ever go through this path, remember to comment why (performance?) and how (casting, safety through runtime interface type check) you're doing it this way instead of using QueryInterface.
My guess is, since internally DX itself will most likely use QueryInterface, you shouldn't find a bottleneck here.
Is there a way to use RAII when creating an array in C++, or do I have to resort to manual memory management via the "new" keyword?
EDIT: By request, some additional details:
First my disclaimer: I'm fairly novice at C++.
Now the details: I simply wanted to iterate through an existing array, SomeClass source[], and parse each element into a storage array, string results[].
So to create that storage string results[], do I need to say string results[] = new string[source.size()] or is there a way to avoid the "new" keyword here via RAII techniques?
It sounds like I'm hearing vector is the way to go. Still, wondered if it's possible with a plain old array.
In C++, especially since we're talking about RAII, we really shouldn't be using C-style arrays at all. The Standard Library provides many containers with different properties that obviate most needs for C-style arrays. By default, you should be using std::vector<> unless you have an understanding of the other containers and a compelling reason not to 1.
Judging from your comments, it looks like what you're trying to do is build an array of string data. This is simple in modern C++ -- just use a std::vector <std::string>.
int main()
{
std::vector <std::string> myStrings;
myStrings.push_back ("hello");
myStrings.push_back ("goodbye");
}
This achieves all your mentioned goals of being RAII and no need to new or delete anything. It also integrates very nicely with other Standard Library facilities, such as find.
I did say "obviate most needs," emphasis mine. There is still occasional need to go old-school. I won't discuss them here since if you actually need it you already know. Which is to say, if you don't know you probably don't need it.
All that being said, std::unique_ptr does support managing C-style arrays with special syntax:
std::unique_ptr <unsigned []> myArray (new unsigned [256]);
the array managed by myArray above will be properly deleted with delete [] at destruction time.
Since there is no unique_ptr analogue to shared_ptr's make_shared, you will either have to use new to actually construct the array, or provide your own (or someone else's) implementation of make_unique
Sidebar: make_unique will be added to C++14.
1 " you should be using std::vector<> unless you have an understanding of the other containers and a compelling reason not to"
This isn't just my opinion. It's also the general (unofficial) opinion of StackOverflow as a whole, C++'s creator Bjarne Stroustup, and the C++ Standard itself (23.1.1).
std::vector<T> is an RAII array type. From the additional information you've given std::vector<string> is appropriate for your use.
string results[] = new string[source.size()]
Just as an aside about arrays, this syntax isn't correct for C++. People teaching C and C++ often teach that arrays and pointers are the same thing, but this is not true and the syntax above shows one of the ways they differ.
The actual relationship between arrays and pointers is
Arrays and pointers are distinct types
In many contexts an implicit conversion from an array to pointer is applied. The conversion results in the address of the array's first element.
pointer arithmetic is defined such that if a pointer points to an element in an array then you can get pointers to other elements of the array by adding and subtracting to the pointer value.
In a some contexts writing an array type will result in a pointer type. In particular, function parameters declared to be of array types are adjusted to be of pointer type. E.g. void foo(int[10]); is effectively identical to void foo(int*);.
So the code you show is declaring an array and initializing it with a pointer. This will result in an error because there's no conversion from pointers to arrays.
Generally you should avoid raw arrays in C++; Arrays just have too many weird rules, such as the weird function parameter rule described above, the rules about when exactly the implicit conversion is performed, prohibitions on assignment and returning arrays from functions, etc. When starting out it's probably best to just stick with the std::array template for arrays with a size known at compile time and the std::vector template for arrays with a size not known at compile time.
You can use std::vector<string> and push_back() each result string in to the vector. You don't have to use new unless you want to avoid vectors and manage memory by yourself
I think a simple template would do the trick in the general case:
template<class T>
class HeapArray {
T* ptr = nullptr;
public:
HeapArray(int size) { ptr = new T[size]; }
~HeapArray() { delete [] ptr; }
operator T*() { return ptr; }
};
You use it as:
HeapArray<std::string> results(source.size());
results[i] = "how cool is this";
basically the HeapArray object is automatically cast'd to its member pointer.
I've been looking into this for the past few days, and so far I haven't really found anything convincing other than dogmatic arguments or appeals to tradition (i.e. "it's the C++ way!").
If I'm creating an array of objects, what is the compelling reason (other than ease) for using:
#define MY_ARRAY_SIZE 10
// ...
my_object * my_array=new my_object [MY_ARRAY_SIZE];
for (int i=0;i<MY_ARRAY_SIZE;++i) my_array[i]=my_object(i);
over
#define MEMORY_ERROR -1
#define MY_ARRAY_SIZE 10
// ...
my_object * my_array=(my_object *)malloc(sizeof(my_object)*MY_ARRAY_SIZE);
if (my_object==NULL) throw MEMORY_ERROR;
for (int i=0;i<MY_ARRAY_SIZE;++i) new (my_array+i) my_object (i);
As far as I can tell the latter is much more efficient than the former (since you don't initialize memory to some non-random value/call default constructors unnecessarily), and the only difference really is the fact that one you clean up with:
delete [] my_array;
and the other you clean up with:
for (int i=0;i<MY_ARRAY_SIZE;++i) my_array[i].~T();
free(my_array);
I'm out for a compelling reason. Appeals to the fact that it's C++ (not C) and therefore malloc and free shouldn't be used isn't -- as far as I can tell -- compelling as much as it is dogmatic. Is there something I'm missing that makes new [] superior to malloc?
I mean, as best I can tell, you can't even use new [] -- at all -- to make an array of things that don't have a default, parameterless constructor, whereas the malloc method can thusly be used.
I'm out for a compelling reason.
It depends on how you define "compelling". Many of the arguments you have thus far rejected are certainly compelling to most C++ programmers, as your suggestion is not the standard way to allocate naked arrays in C++.
The simple fact is this: yes, you absolutely can do things the way you describe. There is no reason that what you are describing will not function.
But then again, you can have virtual functions in C. You can implement classes and inheritance in plain C, if you put the time and effort into it. Those are entirely functional as well.
Therefore, what matters is not whether something can work. But more on what the costs are. It's much more error prone to implement inheritance and virtual functions in C than C++. There are multiple ways to implement it in C, which leads to incompatible implementations. Whereas, because they're first-class language features of C++, it's highly unlikely that someone would manually implement what the language offers. Thus, everyone's inheritance and virtual functions can cooperate with the rules of C++.
The same goes for this. So what are the gains and the losses from manual malloc/free array management?
I can't say that any of what I'm about to say constitutes a "compelling reason" for you. I rather doubt it will, since you seem to have made up your mind. But for the record:
Performance
You claim the following:
As far as I can tell the latter is much more efficient than the former (since you don't initialize memory to some non-random value/call default constructors unnecessarily), and the only difference really is the fact that one you clean up with:
This statement suggests that the efficiency gain is primarily in the construction of the objects in question. That is, which constructors are called. The statement presupposes that you don't want to call the default constructor; that you use a default constructor just to create the array, then use the real initialization function to put the actual data into the object.
Well... what if that's not what you want to do? What if what you want to do is create an empty array, one that is default constructed? In this case, this advantage disappears entirely.
Fragility
Let's assume that each object in the array needs to have a specialized constructor or something called on it, such that initializing the array requires this sort of thing. But consider your destruction code:
for (int i=0;i<MY_ARRAY_SIZE;++i) my_array[i].~T();
For a simple case, this is fine. You have a macro or const variable that says how many objects you have. And you loop over each element to destroy the data. That's great for a simple example.
Now consider a real application, not an example. How many different places will you be creating an array in? Dozens? Hundreds? Each and every one will need to have its own for loop for initializing the array. Each and every one will need to have its own for loop for destroying the array.
Mis-type this even once, and you can corrupt memory. Or not delete something. Or any number of other horrible things.
And here's an important question: for a given array, where do you keep the size? Do you know how many items you allocated for every array that you create? Each array will probably have its own way of knowing how many items it stores. So each destructor loop will need to fetch this data properly. If it gets it wrong... boom.
And then we have exception safety, which is a whole new can of worms. If one of the constructors throws an exception, the previously constructed objects need to be destructed. Your code doesn't do that; it's not exception-safe.
Now, consider the alternative:
delete[] my_array;
This can't fail. It will always destroy every element. It tracks the size of the array, and it's exception-safe. So it is guaranteed to work. It can't not work (as long as you allocated it with new[]).
Of course, you could say that you could wrap the array in an object. That makes sense. You might even template the object on the type elements of the array. That way, all the desturctor code is the same. The size is contained in the object. And maybe, just maybe, you realize that the user should have some control over the particular way the memory is allocated, so that it's not just malloc/free.
Congratulations: you just re-invented std::vector.
Which is why many C++ programmers don't even type new[] anymore.
Flexibility
Your code uses malloc/free. But let's say I'm doing some profiling. And I realize that malloc/free for certain frequently created types is just too expensive. I create a special memory manager for them. But how to hook all of the array allocations to them?
Well, I have to search the codebase for any location where you create/destroy arrays of these types. And then I have to change their memory allocators accordingly. And then I have to continuously watch the codebase so that someone else doesn't change those allocators back or introduce new array code that uses different allocators.
If I were instead using new[]/delete[], I could use operator overloading. I simply provide an overload for operators new[] and delete[] for those types. No code has to change. It's much more difficult for someone to circumvent these overloads; they have to actively try to. And so forth.
So I get greater flexibility and reasonable assurance that my allocators will be used where they should be used.
Readability
Consider this:
my_object *my_array = new my_object[10];
for (int i=0; i<MY_ARRAY_SIZE; ++i)
my_array[i]=my_object(i);
//... Do stuff with the array
delete [] my_array;
Compare it to this:
my_object *my_array = (my_object *)malloc(sizeof(my_object) * MY_ARRAY_SIZE);
if(my_object==NULL)
throw MEMORY_ERROR;
int i;
try
{
for(i=0; i<MY_ARRAY_SIZE; ++i)
new(my_array+i) my_object(i);
}
catch(...) //Exception safety.
{
for(i; i>0; --i) //The i-th object was not successfully constructed
my_array[i-1].~T();
throw;
}
//... Do stuff with the array
for(int i=MY_ARRAY_SIZE; i>=0; --i)
my_array[i].~T();
free(my_array);
Objectively speaking, which one of these is easier to read and understand what's going on?
Just look at this statement: (my_object *)malloc(sizeof(my_object) * MY_ARRAY_SIZE). This is a very low level thing. You're not allocating an array of anything; you're allocating a hunk of memory. You have to manually compute the size of the hunk of memory to match the size of the object * the number of objects you want. It even features a cast.
By contrast, new my_object[10] tells the story. new is the C++ keyword for "create instances of types". my_object[10] is a 10 element array of my_object type. It's simple, obvious, and intuitive. There's no casting, no computing of byte sizes, nothing.
The malloc method requires learning how to use malloc idiomatically. The new method requires just understanding how new works. It's much less verbose and much more obvious what's going on.
Furthermore, after the malloc statement, you do not in fact have an array of objects. malloc simply returns a block of memory that you have told the C++ compiler to pretend is a pointer to an object (with a cast). It isn't an array of objects, because objects in C++ have lifetimes. And an object's lifetime does not begin until it is constructed. Nothing in that memory has had a constructor called on it yet, and therefore there are no living objects in it.
my_array at that point is not an array; it's just a block of memory. It doesn't become an array of my_objects until you construct them in the next step. This is incredibly unintuitive to a new programmer; it takes a seasoned C++ hand (one who probably learned from C) to know that those aren't live objects and should be treated with care. The pointer does not yet behave like a proper my_object*, because it doesn't point to any my_objects yet.
By contrast, you do have living objects in the new[] case. The objects have been constructed; they are live and fully-formed. You can use this pointer just like any other my_object*.
Fin
None of the above says that this mechanism isn't potentially useful in the right circumstances. But it's one thing to acknowledge the utility of something in certain circumstances. It's quite another to say that it should be the default way of doing things.
If you do not want to get your memory initialized by implicit constructor calls, and just need an assured memory allocation for placement new then it is perfectly fine to use malloc and free instead of new[] and delete[].
The compelling reasons of using new over malloc is that new provides implicit initialization through constructor calls, saving you additional memset or related function calls post an malloc And that for new you do not need to check for NULL after every allocation, just enclosing exception handlers will do the job saving you redundant error checking unlike malloc.
These both compelling reasons do not apply to your usage.
which one is performance efficient can only be determined by profiling, there is nothing wrong in the approach you have now. On a side note I don't see a compelling reason as to why use malloc over new[] either.
I would say neither.
The best way to do it would be:
std::vector<my_object> my_array;
my_array.reserve(MY_ARRAY_SIZE);
for (int i=0;i<MY_ARRAY_SIZE;++i)
{ my_array.push_back(my_object(i));
}
This is because internally vector is probably doing the placement new for you. It also managing all the other problems associated with memory management that you are not taking into account.
You've reimplemented new[]/delete[] here, and what you have written is pretty common in developing specialized allocators.
The overhead of calling simple constructors will take little time compared the allocation. It's not necessarily 'much more efficient' -- it depends on the complexity of the default constructor, and of operator=.
One nice thing that has not been mentioned yet is that the array's size is known by new[]/delete[]. delete[] just does the right and destructs all elements when asked. Dragging an additional variable (or three) around so you exactly how to destroy the array is a pain. A dedicated collection type would be a fine alternative, however.
new[]/delete[] are preferable for convenience. They introduce little overhead, and could save you from a lot of silly errors. Are you compelled enough to take away this functionality and use a collection/container everywhere to support your custom construction? I've implemented this allocator -- the real mess is creating functors for all the construction variations you need in practice. At any rate, you often have a more exact execution at the expense of a program which is often more difficult to maintain than the idioms everybody knows.
IMHO there both ugly, it's better to use vectors. Just make sure to allocate the space in advance for performance.
Either:
std::vector<my_object> my_array(MY_ARRAY_SIZE);
If you want to initialize with a default value for all entries.
my_object basic;
std::vector<my_object> my_array(MY_ARRAY_SIZE, basic);
Or if you don't want to construct the objects but do want to reserve the space:
std::vector<my_object> my_array;
my_array.reserve(MY_ARRAY_SIZE);
Then if you need to access it as a C-Style pointer array just (just make sure you don't add stuff while keeping the old pointer but you couldn't do that with regular c-style arrays anyway.)
my_object* carray = &my_array[0];
my_object* carray = &my_array.front(); // Or the C++ way
Access individual elements:
my_object value = my_array[i]; // The non-safe c-like faster way
my_object value = my_array.at(i); // With bounds checking, throws range exception
Typedef for pretty:
typedef std::vector<my_object> object_vect;
Pass them around functions with references:
void some_function(const object_vect& my_array);
EDIT:
IN C++11 there is also std::array. The problem with it though is it's size is done via a template so you can't make different sized ones at runtime and you cant pass it into functions unless they are expecting that exact same size (or are template functions themselves). But it can be useful for things like buffers.
std::array<int, 1024> my_array;
EDIT2:
Also in C++11 there is a new emplace_back as an alternative to push_back. This basically allows you to 'move' your object (or construct your object directly in the vector) and saves you a copy.
std::vector<SomeClass> v;
SomeClass bob {"Bob", "Ross", 10.34f};
v.emplace_back(bob);
v.emplace_back("Another", "One", 111.0f); // <- Note this doesn't work with initialization lists ☹
Oh well, I was thinking that given the number of answers there would be no reason to step in... but I guess I am drawn in as the others. Let's go
Why your solution is broken
C++11 new facilities for handling raw memory
Simpler way to get this done
Advices
1. Why your solution is broken
First, the two snippets you presented are not equivalent. new[] just works, yours fails horribly in the presence of Exceptions.
What new[] does under the cover is that it keeps track of the number of objects that were constructed, so that if an exception occurs during say the 3rd constructor call it properly calls the destructor for the 2 already constructed objects.
Your solution however fails horribly:
either you don't handle exceptions at all (and leak horribly)
or you just try to call the destructors on the whole array even though it's half built (likely crashing, but who knows with undefined behavior)
So the two are clearly not equivalent. Yours is broken
2. C++11 new facilities for handling raw memory
In C++11, the comittee members have realized how much we liked fiddling with raw memory and they have introduced facilities to help us doing so more efficiently, and more safely.
Check cppreference's <memory> brief. This example shows off the new goodies (*):
#include <iostream>
#include <string>
#include <memory>
#include <algorithm>
int main()
{
const std::string s[] = {"This", "is", "a", "test", "."};
std::string* p = std::get_temporary_buffer<std::string>(5).first;
std::copy(std::begin(s), std::end(s),
std::raw_storage_iterator<std::string*, std::string>(p));
for(std::string* i = p; i!=p+5; ++i) {
std::cout << *i << '\n';
i->~basic_string<char>();
}
std::return_temporary_buffer(p);
}
Note that get_temporary_buffer is no-throw, it returns the number of elements for which memory has actually been allocated as a second member of the pair (thus the .first to get the pointer).
(*) Or perhaps not so new as MooingDuck remarked.
3. Simpler way to get this done
As far as I am concered, what you really seem to be asking for is a kind of typed memory pool, where some emplacements could not have been initialized.
Do you know about boost::optional ?
It is basically an area of raw memory that can fit one item of a given type (template parameter) but defaults with having nothing in instead. It has a similar interface to a pointer and let you query whether or not the memory is actually occupied. Finally, using the In-Place Factories you can safely use it without copying objects if it is a concern.
Well, your use case really looks like a std::vector< boost::optional<T> > to me (or perhaps a deque?)
4. Advices
Finally, in case you really want to do it on your own, whether for learning or because no STL container really suits you, I do suggest you wrap this up in an object to avoid the code sprawling all over the place.
Don't forget: Don't Repeat Yourself!
With an object (templated) you can capture the essence of your design in one single place, and then reuse it everywhere.
And of course, why not take advantage of the new C++11 facilities while doing so :) ?
You should use vectors.
Dogmatic or not, that is exactly what ALL the STL container do to allocate and initialize.
They use an allocator then allocates uninitialized space and initialize it by means of the container constructors.
If this (like many people use to say) "is not c++" how can be the standard library just be implemented like that?
If you just don't want to use malloc / free, you can allocate "bytes" with just new char[]
myobjet* pvext = reinterpret_cast<myobject*>(new char[sizeof(myobject)*vectsize]);
for(int i=0; i<vectsize; ++i) new(myobject+i)myobject(params);
...
for(int i=vectsize-1; i!=0u-1; --i) (myobject+i)->~myobject();
delete[] reinterpret_cast<char*>(myobject);
This lets you take advantage of the separation between initialization and allocation, still taking adwantage of the new allocation exception mechanism.
Note that, putting my first and last line into an myallocator<myobject> class and the second ands second-last into a myvector<myobject> class, we have ... just reimplemented std::vector<myobject, std::allocator<myobject> >
What you have shown here is actually the way to go when using a memory allocator different than the system general allocator - in that case you would allocate your memory using the allocator (alloc->malloc(sizeof(my_object))) and then use the placement new operator to initialize it. This has many advantages in efficient memory management and quite common in the standard template library.
If you are writing a class that mimics functionality of std::vector or needs control over memory allocation/object creation (insertion in array / deletion etc.) - that's the way to go. In this case, it's not a question of "not calling default constructor". It becomes a question of being able to "allocate raw memory, memmove old objects there and then create new objects at the olds' addresses", question of being able to use some form of realloc and so on. Unquestionably, custom allocation + placement new are way more flexible... I know, I'm a bit drunk, but std::vector is for sissies... About efficiency - one can write their own version of std::vector that will be AT LEAST as fast ( and most likely smaller, in terms of sizeof() ) with most used 80% of std::vector functionality in, probably, less than 3 hours.
my_object * my_array=new my_object [10];
This will be an array with objects.
my_object * my_array=(my_object *)malloc(sizeof(my_object)*MY_ARRAY_SIZE);
This will be an array the size of your objects, but they may be "broken". If your class has virtual funcitons for instance, then you won't be able to call those. Note that it's not just your member data that may be inconsistent, but the entire object is actully "broken" (in lack of a better word)
I'm not saying it's wrong to do the second one, just as long as you know this.
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?
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.
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.
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.
If you don't want the overhead from std::vector, use boost::array. It is your basic C++ array with static size.
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.