考慮其中丟棄x
元件從所述前一函數的這兩種不同的實現方式:迭代器範圍向量構造或向量擦除是否更快?
template <typename T>
std::vector<T> drop(int size, const std::vector<T>& coll){
if (size<0) return std::vector<T>();
auto sized = size > coll.size() ? coll.size() : size;
typename std::vector<T>::const_iterator first = coll.begin()+sized;
typename std::vector<T>::const_iterator last = coll.end();
return std::vector<T>(first,last);
}
template <typename T>
std::vector<T> drop2(int size, std::vector<T> coll){
if (size<0) return std::vector<T>();
auto sized = size > coll.size() ? coll.size() : size;
coll.erase(coll.begin(),coll.begin()+sized);
return coll;
}
在兩個版本中,一個新的std::vector
被分配(在第二,它被複製作爲一個參數,它是不是一個參考)。其中一個結果由erase()
創建,而另一個則使用原始向量的迭代器創建結果。
有沒有什麼理由相信其中的一個在性能上會比另一個有顯着的不同?
另外,RVO是其中之一還是兩者的保證?
編輯:
下面是測試我沒有,其示出了第一個是相當多的比第二慢:
template<typename F>
void dropExample(F f){
std::cout<<"drop example"<<std::endl;
auto t1 = Clock::now();
for (auto x: range(100000)){
f(2, range(100));
}
auto t2 = Clock::now();
std::cout << "Delta t2-t1: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count()
<< " ms" << std::endl;
}
輸出:
dropExample(drop<int>);
dropExample(drop2<int>);
drop example
Delta t2-t1: 625 ms
drop example
Delta t2-t1: 346 ms
否關於我在for
循環中添加了多少次迭代,數字大致是這樣的,即使對於數十秒的操作秒。
編輯2:
我已經擴充了左值的測試,所建議的意見:
主template<typename F, typename T>
void dropExample2(F f, T vec){
std::cout<<"drop example 2"<<std::endl;
auto t1 = Clock::now();
for (auto x: range(1000)){
f(2, vec);
}
auto t2 = Clock::now();
std::cout << "Delta t2-t1: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count()
<< " ms" << std::endl;
}
然後:
int main(int argc, const char * argv[]) {
auto testrange=range(100000);
dropExample(drop<int>);
dropExample(drop2<int>);
dropExample2(drop<int>,testrange);
dropExample2(drop2<int>,testrange);
return 0;
}
輸出還是暗示第二快得多:
drop example
Delta t2-t1: 564 ms
drop example
Delta t2-t1: 375 ms
drop example 2
Delta t2-t1: 2318 ms
drop example 2
Delta t2-t1: 698 ms
下面是本例中使用輔助功能:
std::vector<int> range(int start, int end, int step);
std::vector<int> range(int start, int end){
if (end<start){
return range(start,end,-1);
}else if (start == end){
return std::vector<int> {start};
}else{
std::vector<int> nums(end-start);
std::iota(nums.begin(),nums.end(),start);
return nums;}
}
std::vector<int> range(int end){
return range(0,end);
}
std::vector<int> range(int start, int end, int step){
std::vector<int> nums{start};
auto next=start+step;
while ((next<end&&start<=end&&step>0)||
(next>end&&start>end&&step<0))
{
nums.push_back(next);
next+=step;
}
return nums;
}
第一個幾乎肯定比第二個快。 –
我認爲在實際的性能數據上進行工作是非常有意義的,通過分析器進行分析,而不僅僅是猜測。 – edmz
沒有保證RVO將被使用。編譯器可能會這樣做,但只有在編譯並找出之前,您才能知道。 – NathanOliver