[英]Alternative/Suggestion for C++ Polymorphism With Virtual Function
我有一個程序,基本上計算C ++中非常大的向量的滾動平均和其他滾動統計。 對於大小為N的向量,我想得到另一個大小為N的向量,其中元素k包含從0到k的滾動統計。 我將使用滾動平均值來說明如下。
該程序有一個對象,該對象具有根據新值和先前統計值更新滾動統計信息的功能。 例如:
inline float update(const float x) {
_n++;
_mean += (x - _mean)/_n;
return _mean;
}
現在我想支持其他統計計算,例如滾動標准偏差,並且計划是使用純虛步驟函數添加純虛擬類作為基類,並創建與不同統計類型對應的不同子類。
我的問題是:因為step函數將是函數的主要部分並將執行數十億次,我是否期望通過從內聯函數切換到虛函數的速度變慢? 對於我想做的事情,還有其他更有效的替代方案嗎? 或者我可能沒有使用正確的設計模式,還有其他更好的方法嗎?
根據我的理解,你可能會使用類似的模板
template <typename Range, typename F>
auto f(const Range& r, F&& f)
{
std::vector<std::decay_t<decltype(f(*r.begin()))>> result;
result.reserve(r.size());
for (const auto& e : v) {
result.push_back(f(e));
}
return result;
}
class MeanCalculator
{
public:
float operator()(float x) const {
n++;
mean += (x - mean) / n;
return mean;
}
private:
std::size_t n = 0;
float mean = 0.0f;
};
class VarianceCalculator
{
public:
float operator()(float x) const {
n++;
// ...
}
private:
std::size_t n = 0;
//...
};
接着
std::vector<float> numbers = /*...*/;
auto means = f(numbers, MeanCalculator{});
auto variances = f(numbers, VarianceCalculator{});
注意:不能使用std::transform
因為它不保證f
的有序應用。
使用多態通常是一個非常好的策略。 它是一種經過驗證且經過時間考驗的方法,可用於構建正確且可維護的軟 vtable問題很少是性能的一個因素。 這里和這里有一些有趣的文章關於vtable的重大優化。
還有一些其他好主意。 例如,查看策略模式 。 您可以使用它在創建處理程序對象時選擇您選擇的函數,可能通過模板或作為ctor的參數。 由於該戰略在施工時被選中一次,因此不會產生vtable懲罰。
另一個相關的想法是使用lambda函數結合一些std :: algorithms。 自C ++ 11以來,這種模式已經變得非常普遍。 lambda用於代替多態。 這是一個簡單的例子,可以為您的項目提供一些想法。
#include <iostream>
#include <vector>
#include <algorithm>
int main(int argc, char*argv[])
{
std::vector<size_t> input = {2,4,6};
std::vector<size_t> output;
auto const operation = std::stoi(argv[1]);
// transform the input vector to the output vector with algorithm selection
switch(operation)
{
// just copy it
case 1:
{
std::for_each(input.begin() ,input.end(), [&](size_t element){
output.push_back(element);
});
break;
}
// divide it by 2
case 2:
{
std::for_each(input.begin() ,input.end(), [&](size_t element){
output.push_back(element/2);
});
break;
}
}
for(auto const & element:output)
std::cout << element << std::endl;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.