所以对于这个例子,假设我有一个名为original的std :: vector,我想把它分成两半,分成两个不同的向量。假设原件具有均匀的元素。
std::vector<int> firstHalf;
std::vector<int> secondHalf;
for (int i = 0, j = original.size()/2; i < original.size() / 2; i++, j++)
{
firstHalf.push_back(original[i]);
secondHalf.push_back(original[j]);
}
更明显的方法是使用两个单独的for循环,一个用于填充firstHalf,另一个用于填充secondHalf。
正在编写for循环,就像我认为不好的做法一样吗?从我的测试来看,这个解决方案比两个单独的for循环更有效。
答案 0 :(得分:11)
实际上,您可以将代码缩减为两行:
std::vector<int> firstHalf(original.begin(), original.begin() + original.size() / 2);
std::vector<int> secondHalf(original.begin() + original.size() / 2, original.end());
<强>原因:强>
push_back
可以在元素数量增加时重新分配内存。 stl会在开始时分配足够的内存。
答案 1 :(得分:6)
我说这不是一种不好的做法,但这也不是很好的做法。
正如杰特的回答所指出的那样,可以将其简化为
std::vector<int> firstHalf(original.begin(), original.begin() + original.size() / 2);
std::vector<int> secondHalf(original.begin() + original.size() / 2, original.end());
我可能会尽量避免重新计算original.size()/2
。
std::size_t halfsize = original.size()/2;
std::vector<int> firstHalf(original.begin(), original.begin() + halfsize);
std::vector<int> secondHalf(original.begin() + halfsize, original.end());
或者,甚至,
std::vector<int>::const_iterator halfway = original.begin() + original.size()/2;
std::vector<int> firstHalf(original.begin(), halfway);
std::vector<int> secondHalf(halfway, original.end());
(在C ++ 11及更高版本中,halfsize
和halfway
的声明可以使用auto
来确定类型。
这些是否更好(例如可读性)是非常主观的。
基本信息是,使用标准算法是一个好主意,其结果是更清晰的代码,并且有明显的等效性。添加一个额外的变量以避免重复的表达式有助于提高可读性。
如果由于某种原因你真的必须使用循环(例如,你所做的不仅仅是将向量的一部分复制到其他向量中),那么考虑一下;
reserve()
push_back()
std::size_t halfsize = original.size()/2
,而不是在循环内重复计算original.size()/2
。如果original
不是const
,则特别相关,因为 - 根据您的循环的作用 - 编译器确定它的大小不会改变的可能性较小。答案 2 :(得分:2)
我会在两个单独的循环中执行此操作。这样,如果元素的数量不均匀并且循环非常简单,它也可以工作。
std::vector<int> firstHalf;
std::vector<int> secondHalf;
size_t middle = original.size()/2;
for (size_t i = 0; i < middle; i++)
{
firstHalf.push_back(original[i]);
}
for (size_t i = middle; i < original.size(); i++)
{
secondHalf.push_back(original[i]);
}
但我不会把你的原始代码称为坏习惯。
答案 3 :(得分:1)
为了通过空间局部性缓存友好,我会使用两个循环。在原始代码中,您在原始数组的各个部分之间来回跳转,索引大小为数组的一半。 以stride-1模式访问数组的元素要好得多。 此外,为子阵列保留空间并保存其他变量(如大小和计数)可能是值得的。
size_t size = original.size();
size_t mid_size = size / 2;
std::vector<int> firstHalf(mid_size);
std::vector<int> secondHalf((size - mid_size == mid_size) ? mid_size : mid_size + 1);
size_t i = 0;
for (; i < mid_size; i++) {
firstHalf[i] = original[i];
}
for (; i < size; i++) {
secondHalf[i - mid_size] = original[i];
}
Jett的回答非常好。
答案 4 :(得分:0)
对于像这样的简单代码,很容易理解发生了什么。但是对于更高级的代码(1000行),我相信大多数人宁愿把它分成2个for
循环。
“效率更高”是什么意思?你看过汇编代码了吗?