开发者

Best way to copy a section of a large array into a smaller one?

I have a situation where I will need an amount of memory determined at runtime to pass to a function. I am using a larger buffer on the stack, then only creating on the heap the space that is necessary:

Foo largeBuf[1024];

int sizeUsed = fillBuff(largeBuf, 1024);

Foo* smallerBuf = new Foo[sizeUsed];

for (UINT i = 0; i < sizeUsed; i++)
{
 smallerBuf[i] = largeBuf[i];
} 

Is there a better 开发者_开发技巧way to do this? Some standard array copying function?


You should probably be using an std::vector, which you can initialize directly from the elements of the larger buffer:

std::vector<Foo> smallerBuf(largeBuf, largeBuf+sizeUsed);


Firstly, you should be using std::vector. There's no reason not to use it. Then use std::copy:

// surely the pointer was an accident
Foo largeBuf[1024];

// int? design should be changed to use an unsigned type
int sizeUsed = fillBuff(largeBuf, 1024); 

// vector, no memory leaks
std::vector<Foo> smallerBuf;
smallerBuf.reserve(sizeUsed);

// copy
std::copy(largeBuf, largeBuf + sizeUsed, std::back_inserter(smallerBuf));

Or just cut to the chase at the end with:

std::vector<Foo> smallerBuf(largeBuf, largeBuf + sizeUsed);

Or another approach:

std::vector<Foo> buf(1024); // this replaces your stack array
buf.resize(fillBuff(&buf[0], 1024)); // copies directly into it, resizes

Note after this last approach, the memory will still be in use. You can force the capacity to shrink with the copy-swap trick:

template <typename T, typename A>
void shrink_to_fit(std::vector<T, A>& pVector)
{
    std::vector<T, A>(pVector).swap(pVector);
}

// ...

shrink_to_fit(buf);

Most ideal, fillBuf would have a way (or another function) to just return the number of elements it will return given a buffer. Then you can just do:

std::vector<Foo> buf(buffSize()); // or whatever
fillBuff(&buf[0], buf.size());


Some standard array copying function?

You mean other than std::copy()?


I'd think the fastest way would be to use memcpy:

const int BUFSIZE = 1024;

Foo* largeBuf = new Foo[BUFSIZE];

int sizeUsed = fillBuff(largeBuf, BUFSIZE);

Foo* smallerBuf = new Foo[sizeUsed];

memcpy(smallerBuf, largeBuf, sizeUsed * sizeof(Foo));

memcpy_s would be safer if on Windows platform:

memcpy_s(smallerBuf, sizeUsed, largeBuf, sizeUsed * sizeof(Foo));


In C++ you could use std::copy. If your function doesn't modify an array you could pass a const pointer and a size without copying array: some_func( largeBuf, sizeUsed );


One idiom you see a lot is to call fillBuff twice. Once to get the size, and once to to the work. Often it's fairly trivial for fillBuff to calculate the needed buffer size:

int sizeUsed = fillBuff(NULL, 0);
Foo* buffer = new Foo[sizeUsed];
fillBuff(buffer, sizeUsed);

If that's not the case, I'd recommend going with a vector:

vector<Foo> buffer;
fillBuff(buffer);

Or, if you must resort to allocating twice, at the very least, specify the size of your buffer:

Foo largeBuf[1024];
int sizeUsed = fillBuff(largeBuf, 1024);

Foo* smallerBuf = new Foo[sizeUsed];
std::copy(largeBuf, largeBuf + sizeUsed, smallerBuf);


How often is this going to occur? If this is going to be in a tight loop, there are lots of different options to consider. You could create stack or heap in advance and do some memory-management yourself. Or you could just pass pointers and share the data if you can do so safely without editing it unknowingly.

If this is a very time-sensitive thing, there are many different implementations, though I'd stay away from creating more layers of objects around things if you don't need to. And if you are filling memory with zeroes, check for implementation speed differences between malloc and setting things to 0 vs just calloc. Or system-specific things like bzero() that sometimes make use of hardware-specific memory commands under-the-hood. Also beware memcpy() vs memmove() - determine which is necessary.

For a bit of fun trivia: http://en.wikipedia.org/wiki/Duff%27s_device :-)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜