【问题标题】:Virtual array sizes虚拟阵列大小
【发布时间】:2021-12-10 15:03:29
【问题描述】:

类是否可以声明一个数组,该数组可以在派生类中被不同长度的数组覆盖?我知道我可以只使用 std::vector ,但它适用于游戏引擎的性能关键阶段,并且由于在编译时长度是已知的,因此似乎应该可以静态地进行。

我的目标是这样的,但没有虚拟和静态成员变量的不可能要求:

struct F {
  virtual static const size_t n;
  Signal[n] inputs;
  Signal getInput(size_t i)
  {
    if(i<n)
      return inputs[i];
  }
};
struct Binary : F {
  static const size_t n=2;
};

【问题讨论】:

  • 没有。不可能,但是您可以使 Base 类成为具有数组大小的模板并以您想要的大小继承它。
  • 没有。在 C++ 中,所有类型都必须具有恒定大小。
  • 没有所谓的“虚拟”成员变量。您如何确定 std::vector 不够快?
  • 不允许使用虚拟成员变量。而且您对数组使用了错误的语法。并且您尝试在变量 n 初始化之前使用它。看来您可能需要多花些时间在some good books 上。
  • 关于向量不够快,你是如何测量的?你测量过吗?

标签: c++ c++20


【解决方案1】:

当你说编译时想想,模板或 constexpr。 像这样:

#include <cassert>
#include <array>
#include <iostream>

//-----------------------------------------------------------------------------

struct Signal
{
    std::size_t id = ++s_id;
    static std::size_t s_id;
};

std::size_t Signal::s_id{ 0 };

//-----------------------------------------------------------------------------

struct FBase
{
    virtual std::size_t size() const = 0;
    virtual ~FBase() = default;

protected:
    FBase() = default;

};

//-----------------------------------------------------------------------------


template<std::size_t N>
struct F : 
    public FBase
{
    Signal inputs[N]{};

    Signal getInput(size_t i)
    {
        assert(i < N);
        return inputs[i];
    }

    std::size_t size() const override
    {
        return N;
    }
};

//-----------------------------------------------------------------------------

struct Binary : 
    public F<2ul>
{
};

struct Trinary :
    public F<3ul>
{
};

//-----------------------------------------------------------------------------

int main()
{
    Binary bin;
    Trinary tri;

    auto signal = bin.getInput(1ul);
    std::cout << signal.id << "\n";

    std::cout << tri.size();
    
    return 0;
}

【讨论】:

  • 这解决了我的问题。我对使用模板的想法不屑一顾,因为我的印象是模板化的基类与虚函数不兼容,但经过测试,它确实适用于我的特定情况。谢谢。
  • @Ptolom 尝试添加struct Trinary : public F&lt;3ul&gt;{};,你会发现TrinaryBinary 没有共同的基类。从这个意义上说,它打破了多态性。如果没有模板,它们将共享一个公共基类。
  • 啊哈。我知道我错过了一些东西。我会按照大家的建议做,先用 std::vector 衡量性能,然后再增加复杂性。
  • 我根据你的输入做了这个例子,没有提到虚函数。更新的示例也将其添加到组合中;)但是是的,测量总是好的,分支预测/数据局部性之类的东西通常也会产生很大的影响
【解决方案2】:

也许您可以在基类中使用指向 Signal 的指针,然后每个继承的类将指针初始化为不同大小的数组。这将克服类维度上的问题。只要记住声明虚拟析构函数并手动删除数组的内存即可。

【讨论】:

  • 如果你使用std::vector而不是手动分配,你就不必记得在析构函数中删除它。
猜你喜欢
  • 2011-03-25
  • 2011-01-12
  • 1970-01-01
  • 2016-09-26
  • 2014-04-06
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多