优化将一个数组插入另一个数组 C/C++
Posted
技术标签:
【中文标题】优化将一个数组插入另一个数组 C/C++【英文标题】:Optimizing Inserting One Array into Another Array C/C++ 【发布时间】:2011-11-16 14:31:38 【问题描述】:我的自定义动态数组类中有这个函数,它允许用户将另一个数组插入到这个数组中。它有效,但我有 99% 的把握这不是最快的解决方案,我想知道是否可以结合两个 for
循环来提高性能?如果是这样,怎么做?我有点卡住了。
提前致谢。
void insertrange(T item[], int sizerange, int index)
int k = this->size;
int j = 0;
if(this->size + sizerange >= this->capacity) //if the size + added size are bigger than the capacity
this->enlarge(this->capacity + sizerange); //enlarge the array
for(k; k >= index; k--) //for every element from the end to the index where to add the new array
this->array[k + sizerange] = a[k]; //replace the element to his new spot
for(j; j < sizerange; j++) //vor every element in the new array
this->array[index + j] = item[j]; //place it in the new spot
size += sizerange;
【问题讨论】:
在尝试优化之前测量性能。如果有,瓶颈在哪里? 您是否通过分析发布版本证明这是您应用程序中的真正瓶颈? 我假设这是家庭作业 - 否则你只会使用 std::vector! 这不是真正的瓶颈,也不是功课。我试图制作一个比 std::vector 更快的数组,所以我试图压缩我能做到的每一点性能:) 你可能发现std::copy
和std::reverse_copy
比for
循环快,如果T
是一个POD类型并且你的库有一个汇编优化执行。你必须测量它才能确定。 (无论如何,这可能是一个好主意,既为了可读性,又为了减少引入像第一个循环中的错误这样的错误的机会)。
【参考方案1】:
我认为关键是您不必复制空单元格。
void insertrange(T item[], int sizerange, int index)
// This actually points past the end of the current array, right?
int onePastLastEntry = this->size;
// Still need to make sure the new array is large enough
if(this->size + sizerange >= this->capacity) //if the size + added size are bigger than the capacity
this->enlarge(this->capacity + sizerange); //enlarge the array
// you should be able to go forward instead of backwards
for(i = index; i < onePastLastEntry ; i++)
// move the current element
this->array[i + sizerange] = a[i];
// then copy the new value
this->array[i] = item[i - index];
您实际上可以从零开始循环,也可以转到onePastLastEntry - index
,但这会使数学变得奇怪:
// you should be able to go forward instead of backwards
for(i = 0; i < onePastLastEntry - index; i++)
// now you have to add the index in two places here
this->array[i + index + sizerange] = a[i + index];
// and add the index in the copy as well
this->array[i + index] = item[i];
【讨论】:
【参考方案2】:我看到的唯一可能的性能优势是,每次数组变大时,动态分配都会减少。在大多数情况下,每次需要重新分配时将容量乘以 2 会更好。
【讨论】:
我猜这是通过放大功能在幕后处理的。如果不是,应该是。 我明白了,我明白了。谢谢:) 我认为以某种方式组合两个循环会更快。感谢您的回答【参考方案3】:你的 k for 循环中有一个额外的副本。 k 索引应该从 size-1 开始,而不是 size,因此您将复制一个超出数组末尾的额外元素。但是,这将提供可以忽略不计的加速。如果需要大幅提升性能,您应该考虑优化放大功能或使用与数组不同的数据结构。
【讨论】:
【参考方案4】:您可以移动元素,而不是复制它们:
for(k; k >= index; k--)
this->array[k + sizerange] = std::move(a[k]);
另一个可能的改进,特别是对于具有昂贵的默认构造函数的类,是使用移动构造函数就地构造 T。当您分配时,而不是使用new T[]
进行分配,它默认构造每个元素,而是使用new char[]
或malloc
分配原始字节。然后你可以使用placement new来移动构造对象。
【讨论】:
以上是关于优化将一个数组插入另一个数组 C/C++的主要内容,如果未能解决你的问题,请参考以下文章
如何在另一个数组中的用户指定位置插入一个数组并获取结果数组?
有一个从小到大排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。