将大阵列的一部分复制到较小的阵列的最佳方法是什么?

时间:2010-07-08 19:22:07

标签: c++ arrays

我遇到一种情况,我需要在运行时确定一定量的内存以传递给函数。我在堆栈上使用更大的缓冲区,然后只在堆上创建必要的空间:

Foo largeBuf[1024];

int sizeUsed = fillBuff(largeBuf, 1024);

Foo* smallerBuf = new Foo[sizeUsed];

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

有更好的方法吗?一些标准的阵列复制功能?

7 个答案:

答案 0 :(得分:6)

您可能应该使用std::vector,您可以直接从较大缓冲区的元素初始化:

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

答案 1 :(得分:5)

首先,您应该使用std::vector。没有理由不使用它。然后使用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));

或者只是切断追尾:

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

或另一种方法:

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

请注意,在最后一种方法之后,内存仍将被使用。您可以使用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);

最理想的是,fillBuf会有一种方式(或其他函数)只返回给定缓冲区时它将返回的元素数。然后你可以这样做:

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

答案 2 :(得分:4)

一些标准的阵列复制功能?

你的意思是除了std :: copy()?

答案 3 :(得分:1)

我认为最快的方法是使用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));
如果在Windows平台上,

memcpy_s会更安全:

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

答案 4 :(得分:0)

在C ++中,您可以使用std::copy。如果你的函数没有修改数组,你可以传递一个const指针和一个大小而不复制数组:some_func( largeBuf, sizeUsed );

答案 5 :(得分:0)

你看到的一个习惯用法是两次拨打fillBuff。一旦得到大小,一次到工作。 fillBuff计算所需的缓冲区大小通常是微不足道的:

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

如果情况并非如此,我建议使用矢量:

vector<Foo> buffer;
fillBuff(buffer);

或者,如果您必须分配两次,至少要指定缓冲区的大小:

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

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

答案 6 :(得分:0)

这种情况多久发生一次?如果这将是一个紧凑的循环,有很多不同的选择要考虑。您可以提前创建堆栈或堆,并自己进行一些内存管理。或者你可以只是传递指针并分享数据,如果你可以安全地这样做,而无需在不知不觉中进行编辑。

如果这是一个非常时间敏感的事情,那么有许多不同的实现,但如果你不需要,我会远离创建更多的对象层。如果你用零填充内存,检查malloc和设置之间的实现速度差异为0而不是calloc。或者特定于系统的东西,比如bzero(),有时会使用特定于硬件的内存命令。还要注意memcpy()vs memmove() - 确定哪一个是必要的。

有点有趣的琐事:http://en.wikipedia.org/wiki/Duff%27s_device: - )

相关问题