簡體   English   中英

具有虛函數的C ++多態的替代/建議

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM