C++ array resize

Started by
22 comments, last by Misery 12 years, 9 months ago
Hi,

I need to resize copy an array as fast as possible. Is it a good way, or there are some dangers I cannot see?
(Lets assume that new size is greater than previous).

int N=SomeValue, NewSize=SomeValue;
int *array=new int[N];

//making a temporary array:
int *tmp=new int[NewSize];
for (int i=0;i<N;i++) tmp=array;
delete[] array;
array=tmp;


Or do I need to allocate array again and copy it from tmp to array and then delete tmp?
Will that work fine?

Thanks on advance for help :]
Advertisement
I would use std::copy instead of a homemade loop.
No need to allocate another new array, that works fine.
But, why not std::vector?

https://www.kbasm.com -- My personal website

https://github.com/wqking/eventpp  eventpp -- C++ library for event dispatcher and callback list

https://github.com/cpgf/cpgf  cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.


No need to allocate another new array, that works fine.
But, why not std::vector?


Because it would be vector<bool> and i've heard it is not safe to use it.

Thanks gyus for answers :]]

[quote name='wqking' timestamp='1309770782' post='4830853']
No need to allocate another new array, that works fine.
But, why not std::vector?


Because it would be vector<bool> and i've heard it is not safe to use it.

Thanks gyus for answers :]]
[/quote]
vector<bool> is fine to use but I wouldnt have used a loop just memcpy the memory from the old array in to the new one.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

You can often use std::vector<unsigned char> instead of std::vector<bool>. std::vector<bool> is unusual in certain ways, but isn't necessarily unsafe.

What is your usage of the array? Is it resized once, or is it resized multiple times? If multiple, consider over-allocating to amortise the cost of individual resize actions. Also consider wrapping the array in a class, so you can separate the memory management from other code and can directly control when and how much to allocate, while maintaining all the invariants you need.

Because it would be vector<bool> and i've heard it is not safe to use it.

The only potential problem I'm aware of is that you can't just take the address of anything returned by operator[] for an std::vector<bool>. That is something one should be aware of but not something that prohibits the use of the entire class. Could you expand a bit about the safety issues of the bool specialization of std::vector? There are a lot of myths and legends going around, especially from before the time of proper standardization.

That aside, what about Boost's bitset/dynamic_bitset?
I will probably use this bit array to store my extended arithmetic numbers for mesh generator, and as a flags container for finite elements properties.
And maybe for iterative corrections of large systems of linear equations.
The problem is that this will be the adaptive mesh for largre tasks (millions of nodes) in partial differential eqs. Now I am playing with different things
just to see possibilities it gives, etc. I needed to have my bitarray as small as possible and as fast as possible. I'm not saying I've done it better
than programming-artists like You gyus or Creators of STL or BOOST, but the thing is that I really need to have absolute control over this project.
I cannot afford to finally find a bug for solving which I will have to wait until next release of some library. That happend to me once
and I almost lost my job. So if it is possible I prefer to use my own code - not so efficient and well made but easy to modify etc.

And the second thing is that I am just learning, and trying to do some things.

to GDNet+: I have wrapped it in class and I will use some of the tips You wrote. However now I am just trying to make a quite good bit array :]

Thank You guys very very much for Your help :]

PS.: If someone wishes to see that class (unfinished yet) I paste it here:


#ifndef TBITARRAY_H_INCLUDED
#define TBITARRAY_H_INCLUDED
#include <stdlib.h>
#include <string>


class TBitArray
{
class TEightBits; //internal class implementing a byte with access to every bit
private:
TEightBits* Bits;
unsigned int BitsNumber; //number of bits

public:

inline TBitArray() //constructor
{
BitsNumber=0;
Bits=NULL;
}


inline TBitArray(unsigned int NumOfBits) //meritorical nonstructor
{
int NumOfBytes=NumOfBits/8; //jesli NumOfBits nie miesci sie w calkowitej liczbie bajtow
if (NumOfBits%8>0) NumOfBytes++; //trzeba zwiekszyc o 1 liczbe bajtow
BitsNumber=0;
Bits=NULL;
Bits=new TEightBits[NumOfBytes];
BitsNumber=NumOfBits;
}


inline ~TBitArray()
{
BitsNumber=0;
delete[] Bits;
Bits=NULL;
}


inline unsigned int GetNumberOfBytes(void)
{
unsigned int NumOfBytes=BitsNumber/8;
if (BitsNumber%8>0) NumOfBytes++;
return NumOfBytes;
}

inline bool GetBit(unsigned int BitPos)
{
return Bits[BitPos/8].GetBit(BitPos%8);
}

inline void SetBit(bool Bit,unsigned int BitPos)
{
Bits[BitPos/8].SetBit(Bit,BitPos%8);
}

inline void Resize(unsigned int NewSizeInBits)
{
unsigned int NewNumOfBytes=NewSizeInBits/8,
NumOfBytes=BitsNumber/8;
if (NewSizeInBits%8>0) NewNumOfBytes++;
if (BitsNumber%8>0) NumOfBytes++;

if (NewNumOfBytes!=NumOfBytes) //dodac dodatkowe warunki
{
TEightBits *tmp=new TEightBits[NewNumOfBytes];
std::copy(Bits,Bits+Min(NewNumOfBytes,NumOfBytes),tmp); //a faster stuff
delete[] Bits;
Bits=tmp;
BitsNumber=NewSizeInBits;
}
}

inline void Copy(const TBitArray& that)
{
unsigned int NewNumOfBytes=that.BitsNumber/8,
NumOfBytes=BitsNumber/8;
if (that.BitsNumber%8>0) NewNumOfBytes++;
if (BitsNumber%8>0) NumOfBytes++;

if (NewNumOfBytes!=NumOfBytes)
{
delete[] Bits;
Bits=NULL;
Bits=new TEightBits[NewNumOfBytes];
}
std::copy(that.Bits,that.Bits+NewNumOfBytes,Bits);
BitsNumber=that.BitsNumber;
}


inline unsigned int SizeInBytes(void)
{
unsigned int NumOfBytes=BitsNumber/8;
if (BitsNumber%8>0) NumOfBytes++;
return NumOfBytes;
}

inline void Negation(void)
{
for (unsigned int i=0;i<SizeInBytes();i++) Bits.Negation();
}

inline void IncByLastBit(void)
{

}

inline void IncByFirstBit(void)
{

}

std::string ToString(void)
{
std::string RetStr(BitsNumber,'0');
for (unsigned int i=0;i<BitsNumber;i++) if(GetBit(i))RetStr='1';
return RetStr;
}

private:

inline unsigned int Min(unsigned int a,unsigned int b)
{
if(a<b) return a; else return b;
}

class TEightBits //internal class implementing a byte with access to every bit
{
private:
unsigned char bits;

public:
TEightBits()
{
bits=0;
}

inline bool GetBit(unsigned short BitPos)
{
return (bits & (1 << BitPos));
}

inline void SetBit(bool Bit, unsigned short BitPos)
{
bits |= Bit << BitPos;
}

inline void NegationBit(unsigned int BitPos)
{
bits ^= 1 << BitPos;
}

inline unsigned int ElementSize(void) const
{
return 8; //bits
}

inline void Negation(void)
{
bits=~bits;
}

inline void operator = (const TEightBits &Byte)
{
bits=Byte.bits;
}

/*
//operators
inline bool operator == (const TEightBits &Byte)
{
return (bits==Byte.bits);
}

inline bool operator != (const TEightBits &Byte)
{
return (bits!=Byte.bits);
}

inline bool operator >= (const TEightBits &Byte)
{
return (bits>=Byte.bits);
}

inline bool operator <= (const TEightBits &Byte)
{
return (bits<=Byte.bits);
}

inline bool operator > (const TEightBits &Byte)
{
return (bits>Byte.bits);
}

inline bool operator < (const TEightBits &Byte)
{
return (bits<Byte.bits);
}
*/
};
};

#endif // TBITARRAY_H_INCLUDED


No need to allocate another new array, that works fine.

I'm assuming the existing array is populated and used prior to resizing (else it wouldn't be a resize).
A couple of things:

First, I would talk out the usage of Boost with my employers. As far as I am concerned, Boost is an integral part of C++ and contains mostly things that should have been in the standard library in the first place (and some of them now are in C++0x). Unless you are working on a compiler with horrible template support, a very embedded platform with limited capabilities or suffer from some weird license issues (extremely weird, considering Boost's rather permissive license) there is not much reason not to use Boost.
In general using well-tested code (and Boost is that) will be much faster than writing it on your own, never mind all those teeny tiny bugs you have to weed out of your own code. Even if Boost contains a bug (not impossible but increasingly unlikely in the well-matured core libraries) I would expect the Boost mailing list could offer a fix for a reproducible bug within a day or two. At worst, you could hack a fix together yourself since the code is all there.

Second, I notice you have a class to grant access to the single bits of a byte. Have you made sure that class is not padded by the compiler to 32/64 bit boundaries? Have you checked in the standard that allocating an array of these classes will never introduce any padding? Because if you didn't, you are wasting memory by a factor of four or eight.

Last, you don't need to specify functions as inline if they are declared in the class body. Neither do you need to specify void for no-argument functions (that's C).

This topic is closed to new replies.

Advertisement