【问题标题】:Using new with fixed length array typedef使用带有固定长度数组 typedef 的 new
【发布时间】:2011-03-23 13:29:11
【问题描述】:

如何为固定长度数组定义 typedef,以便我也可以“新建”。以下方法不起作用:

typedef double Vector[3];
Vector *v = new Vector; // does not compile

我们正在尝试将一些旧的 C 代码封装到 C++ 中,这些代码以通用方式处理 float *float (*)[3]

【问题讨论】:

  • 您应该包含错误,而不是仅仅说“不起作用”(这完全没有意义并且在本网站上被过度使用)。据推测,它类似于error: cannot convert 'double*' to 'double (*)[3]' in initialization

标签: c++ typedef


【解决方案1】:

指向double[3] 的指针是double * - 所以这会起作用:

  typedef double Vector[3];
  double *v = new Vector;

但我建议你不要那样使用它——删除你需要array-delete-operator的数组:

  delete[] v;

但在new Vector 上,您看不到它是一个数组,因此它可能会被遗忘。

Scott Meyers Effective C++ 处理了这种情况(强烈建议避免)。所以最好不要在这里使用 typedef。

【讨论】:

  • 迈耶斯推荐什么?
  • Meyers 建议使用向量。我不知道这对原始问题是否有帮助,因为它应该表现得像一个 C 数组,但对于 C++,使用 STL-Containers 是要走的路。
【解决方案2】:
class Vector
{
public: // methods
    double * data() { return mData; }
    const double * data() const { return mData; }
    double & operator[](int i) { return mData[i]; }
    double operator[](int i) const { return mData[i]; }
private: // attributes
    double mData[3];
};

允许

Vector * pv = new Vector;
Vector & v = *pv;
v[0] = 1;
v[1] = 2;
v[2] = 3;

pass_it_to_legacy_lib(v.data());

delete pv;

原始示例的一个问题是它会调用new 运算符,而new[] 实际上是正确的。此外,这将使得必须使用 delete[] 而不是普通的 delete 变得不明显。

类方法不需要new[],充分利用了先验固定长度。

【讨论】:

    【解决方案3】:

    如果您乐于在您的 C++ 代码中使用模板,那么这样的事情可能会起作用..

    template <typename T, int S>
    struct array
    {
      array() : _inst() {}
    
      template<typename _F>
      void operator()(_F & f)
      {
        f(_inst); 
      }
    
      operator T*() { return _inst; }
    
      // real array
      T _inst[S];
    };
    
    typedef array<double, 4> d4;
    
    void foo(double*)
    {
    
    }
    
    int main(void)
    {
      d4 d; // no need for new, but you can use if you want
    
      // first way to call is to pass the function to the array object, which will then
      // visit
      d(foo);
      // take advantage of the type operator (operator T*)
      foo(d);
    }
    

    【讨论】:

    • 我发现“双重表示法”operator() 有点奇怪而且用处不大,因为它只适用于采用单个 double * 参数的函数。但我知道,在微分几何中,您习惯于将向量视为作用于函数的东西;-)(作为方向导数运算符)
    【解决方案4】:
    #include <cassert>
    #include <vector>
    
    using namespace std;
    
    template<typename Type, int Dimension>
    const vector<Type> make_fixed_vector(const Type& value = Type())
    {
        return vector<Type>(Dimension, value);
    }
    
    int main(void)
    {
        vector<int> v3 = make_fixed_vector<int, 3>();
        assert(v3.size() == 3);
    }
    

    C++1x 编译器能够推断出变量的类型,这在使用这种技术声明多维“固定”向量时非常方便:

        .
        .
        .
    template<typename Type, int Rows, int Columns>
    const vector<vector<Type> > make_fixed_vector_vector(const Type& value = Type())
    {
        return vector<vector<Type> >(Rows, make_fixed_vector<Type, Columns>(value));
    }
    
    int main(void)
    {
        auto vv = make_fixed_vector_vector<int, 3, 4>(42);
    
        assert(vv.size() == 3);
        assert(vv[0].size() == 4);
        assert(vv[0][0] == 42);
        assert(vv[2][3] == 42);
    }
    

    在为列表表达式编写解析器函数时,我有这个简单的想法,该函数将返回一个固定大小的整数向量向量。例如,vector&lt;vector&lt;int&gt; &gt;(1) 用于“(0,8)”之类的表达式,而vector&lt;vector&lt;int&gt; &gt;(2) 用于“(3-4)(5)”之类的表达式等等。在应用程序中,最多可以有 5 个带括号的定义,它们表示对程序数据的逻辑引用。我首先尝试解析vector&lt;vector&lt;int&gt; &gt;(5)。工作了吗?好的,得到了​​参考类型A,最详细的一个。否则vector&lt;vector&lt;int&gt; &gt;(4) 表示引用类型 B 等。

    为此,make_fixed_vector 运行良好,但从一般角度来看,该技术存在缺陷。最值得注意的是,由于make_fixed_vector 不返回真实类型,因此无法在编译时检查其维度。在运行时reserveresizepush_back 调用是可能的。而且,由于函数模板不能有默认模板参数,自定义分配器需要更多的输入:

    template<typename Type, int Dimension, template<typename> class Allocator>
    const vector<Type Allocator<Type> > make_fixed_vector(const Type& value = Type())
    {
        return vector<Type, Allocator<Type> >(Dimension, value);
    }
    
    vector<int> v3 = make_fixed_vector<int, 3, std::allocator>();
    

    等等。等等。但是这种技术使较小的项目保持基本。除非这种美德是相关的,否则 Boost 的 boost::array 可能更现实。

    【讨论】:

      猜你喜欢
      • 2011-05-30
      • 1970-01-01
      • 2011-05-18
      • 1970-01-01
      • 1970-01-01
      • 2017-11-11
      • 2019-02-28
      • 2020-08-31
      相关资源
      最近更新 更多