<p><br>
On Jul 26, 2012 6:43 PM, "Alpár Jüttner" <<a href="mailto:alpar@cs.elte.hu">alpar@cs.elte.hu</a>> wrote:<br>
><br>
> Hi,<br>
><br>
> > > * The way how the memory block is allocated is wrong. Sometimes<br>
> > > (not always it crashes at the call of delete []. Does anyone<br>
> > > know how to correctly allocate a memory block which is to be<br>
> > > deallocated by delete []?<br>
> > > An alternative is the use std::allocator<>, but it seems to<br>
> > > increase the memory footprint a bit.<br>
> ><br>
> > I would use char array allocation and deallocation and call the<br>
> > destructor of the items directly:<br>
> > _array = reinterpret_cast<T*>(operator new char[size*sizeof(T)]);<br>
> > delete[] reinterpret_cast<char*>(_array);<br>
><br>
> Unfortunately is works only if T has a default constructor, so it is not<br>
> an option.</p>
<p>Fix:<br>
_array = reinterpret_cast<T*>(new char[size*sizeof(T)]);</p>
<p>I think, it should work, the variant implementation in LEMON works very similarly. For which operation do you need the default constructor of T?</p>
<p>> > The problem is with your code that a normal p = new T[n] returns a<br>
> > memory address for which<br>
> > *(reinterpret_cast<int*>(reinterpret_cast<T>(p) - sizeof(T*))) == n<br>
> > (it's not completely true for objects without destructor). So it<br>
> > allocates more memory than you did, and stores the array size in the<br>
> > first word - before the returned pointer. At the delete[] call, it<br>
> > tries to find this size information, which is missing in your<br>
> > implementation. Otherwise, the implementation can be compiler<br>
> > dependent, that's way I would not depend on it, and i would use the<br>
> > char* allocation.<br>
><br>
> Alright, but how to allocate a memory block appropriate for delete[],<br>
> then? C++ provides (user definable) 'operator new()' for allocating<br>
> memory blocks to be deallocated by 'delete'. What is the array<br>
> counterpart of this operator?<br>
I think you can redefine new only if delete is redefined, as well. But the default implementation is defined.</p>
<p>><br>
> > You need also handle exceptions in the constructors properly. If one<br>
> > of them breaks, then you have to call the destructor of the already<br>
> > constructed items, and then rethrow the exception.<br>
><br>
> You are right, thank you.<br>
><br>
> Alpar<br>
><br>
><br>
> ><br>
> > Balazs<br>
> ><br>
> > On Thu, Jul 26, 2012 at 4:06 PM, Alpár Jüttner <<a href="mailto:alpar@cs.elte.hu">alpar@cs.elte.hu</a>> wrote:<br>
> > > Two caveats concerning the array implementation of the previous mail:<br>
> > ><br>
> > > * The declarations 'T1 t1' in the constructor parameter lists<br>
> > > should be changed to 'T1 &t1' or 'const T1 &t1'. In fact, both<br>
> > > versions should be implemented. Even worse, all possible<br>
> > > combinations of const/non-const parameters should be<br>
> > > implemented. Any idea how to do it correctly? Maybe a pair of<br>
> > > recursive call of the constructor having one less parameters?<br>
> > > * The way how the memory block is allocated is wrong. Sometimes<br>
> > > (not always it crashes at the call of delete []. Does anyone<br>
> > > know how to correctly allocate a memory block which is to be<br>
> > > deallocated by delete []?<br>
> > > An alternative is the use std::allocator<>, but it seems to<br>
> > > increase the memory footprint a bit.<br>
> > ><br>
> > > Regards,<br>
> > > Alpar<br>
> > ><br>
> > ><br>
> > > On Thu, 2012-07-26 at 10:24 +0200, Alpár Jüttner wrote:<br>
> > >> Hi,<br>
> > >><br>
> > >> It is a common problem that one would like use an array of objects, but<br>
> > >> (s)he can't because the object either (a) not default constructible or<br>
> > >> (b) not copyable. Notably, it is a regular question from LEMON users how<br>
> > >> to create an array of NodeMap<>.<br>
> > >><br>
> > >> If the object is at least default constructible, than you can use<br>
> > >> new[]/delete[], otherwise (such as for NodeMap) the only reasonable<br>
> > >> solution is using std::vector<Object *> and manually and individually<br>
> > >> allocating/deleting the objects.<br>
> > >><br>
> > >> Note, that even std::array introduced by C++11 fails to solve this<br>
> > >> problem, for (1) its size is determined compile-time, and (2) does not<br>
> > >> resolve (a).<br>
> > >><br>
> > >> Instead, I propose another Array implementation, please find the<br>
> > >> prototype at the end of this mail.<br>
> > >><br>
> > >> This is a fixed-size array, but the size is determined run time, i.e. at<br>
> > >> construction. Moreover, the objects in the array are constructed using<br>
> > >> the parameters passed to Array itself. Thus you can do this:<br>
> > >><br>
> > >> ListDigraph g;<br>
> > >> ListDigraph::Node n;<br>
> > >> ...<br>
> > >> int size = 12;<br>
> > >> Array<ListDigraph::NodeMap<int> > map_array(size, g);<br>
> > >> map_array[2][n]=5;<br>
> > >> map_array[3][n]+=11;<br>
> > >><br>
> > >> or even:<br>
> > >><br>
> > >> Array<ListDigraph::NodeMap<bool> > map_array(size, g, true);<br>
> > >> map_array[2][n]=false;<br>
> > >><br>
> > >> What do you think of this idea? Does it worth including into LEMON?<br>
> > >><br>
> > >> Plus a design question - do we need the _size member? Omitting it would<br>
> > >> be result in a narrower layer above the simple pointer it actually<br>
> > >> wraps. On the other, it allows a more stl-like interface with size(),<br>
> > >> iterators, begin(), end() etc. But to be honest, I see very little use<br>
> > >> of them here, except for size().<br>
> > >><br>
> > >> Regards,<br>
> > >> Alpar<br>
> > >><br>
> > >><br>
> > >> // *****************************************************<br>
> > >> // * Array class *<br>
> > >> // *****************************************************<br>
> > >><br>
> > >> template<class T ><br>
> > >> class Array {<br>
> > >> T * _array;<br>
> > >> size_t _size;<br>
> > >><br>
> > >> ///Copying is not allowed.<br>
> > >> Array(const Array &);<br>
> > >> ///Copying is not allowed.<br>
> > >> Array &operator=(const Array &);<br>
> > >><br>
> > >> public:<br>
> > >> explicit Array(size_t size) : _array(new T[size]), _size(size) {}<br>
> > >> template <class T1><br>
> > >> explicit Array(size_t size, T1 t1)<br>
> > >> : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),<br>
> > >> _size(size)<br>
> > >> {<br>
> > >> for(size_t i=0;i<size;i++)<br>
> > >> new (_array+i) T(t1);<br>
> > >> }<br>
> > >> template <class T1, class T2><br>
> > >> explicit Array(size_t size, T1 t1, T2 t2)<br>
> > >> : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),<br>
> > >> _size(size)<br>
> > >> {<br>
> > >> for(size_t i=0;i<size;i++)<br>
> > >> new (_array+i) T(t1,t2);<br>
> > >> }<br>
> > >> template <class T1, class T2, class T3><br>
> > >> explicit Array(size_t size, T1 t1, T2 t2, T3 t3)<br>
> > >> : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),<br>
> > >> _size(size)<br>
> > >> {<br>
> > >> for(size_t i=0;i<size;i++)<br>
> > >> new (_array+i) T(t1,t2,t3);<br>
> > >> }<br>
> > >> template <class T1, class T2, class T3, class T4><br>
> > >> explicit Array(size_t size, T1 t1, T2 t2, T3 t3, T4 t4)<br>
> > >> : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),<br>
> > >> _size(size)<br>
> > >> {<br>
> > >> for(size_t i=0;i<size;i++)<br>
> > >> new (_array+i) T(t1,t2,t3,t4);<br>
> > >> }<br>
> > >> template <class T1, class T2, class T3, class T4, class T5><br>
> > >> explicit Array(size_t size, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)<br>
> > >> : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),<br>
> > >> _size(size)<br>
> > >> {<br>
> > >> for(size_t i=0;i<size;i++)<br>
> > >> new (_array+i) T(t1,t2,t3,t4,t5);<br>
> > >> }<br>
> > >><br>
> > >> ~Array() { delete [] _array; }<br>
> > >> operator T* () { return _array; }<br>
> > >> size_t size() { return _size; }<br>
> > >> };<br>
> > >> }<br>
> > >><br>
> > >><br>
> > >> _______________________________________________<br>
> > >> Lemon-devel mailing list<br>
> > >> <a href="mailto:Lemon-devel@lemon.cs.elte.hu">Lemon-devel@lemon.cs.elte.hu</a><br>
> > >> <a href="http://lemon.cs.elte.hu/mailman/listinfo/lemon-devel">http://lemon.cs.elte.hu/mailman/listinfo/lemon-devel</a><br>
> > >><br>
> > >><br>
> > >><br>
> > >> _______________________________________________<br>
> > >> Lemon-user mailing list<br>
> > >> <a href="mailto:Lemon-user@lemon.cs.elte.hu">Lemon-user@lemon.cs.elte.hu</a><br>
> > >> <a href="http://lemon.cs.elte.hu/mailman/listinfo/lemon-user">http://lemon.cs.elte.hu/mailman/listinfo/lemon-user</a><br>
> > >><br>
> > ><br>
> > ><br>
> > > _______________________________________________<br>
> > > Lemon-user mailing list<br>
> > > <a href="mailto:Lemon-user@lemon.cs.elte.hu">Lemon-user@lemon.cs.elte.hu</a><br>
> > > <a href="http://lemon.cs.elte.hu/mailman/listinfo/lemon-user">http://lemon.cs.elte.hu/mailman/listinfo/lemon-user</a><br>
> ><br>
><br>
><br>
><br>
</p>