Использование new с массивом фиксированной длины typedef - PullRequest
2 голосов
/ 23 марта 2011

Как мне определить typedef для массива фиксированной длины, чтобы я также мог 'new'.Следующее не работает:

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

Мы пытаемся включить в C ++ некоторый старый код C, который обрабатывает float * и float (*)[3] в общем виде.

Ответы [ 4 ]

3 голосов
/ 23 марта 2011
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[] и использует все преимущества априорной фиксированной длины.

2 голосов
/ 23 марта 2011

Указатель на double[3] равен double * - так что это будет работать:

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

Но я предлагаю вам не использовать его таким образом - чтобы удалить массив, вам нужен массив-оператор удаления:

  delete[] v;

Но на new Vector вы не видите, что это массив, и поэтому его можно забыть.

Этот случай обрабатывается (и настоятельно рекомендуется избегать) в Скотт Мейерс Эффективный C ++ .Так что лучше не используйте здесь typedef.

0 голосов
/ 06 сентября 2011
#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<vector<int> >(1) для выражения типа "(0,8)", но vector<vector<int> >(2) для выражения типа "(3-4) (5)" и так далее.В приложении возможно до 5 заключенных в скобки определений, которые представляют логические ссылки на данные программы.Я сначала пытаюсь разобрать vector<vector<int> >(5).Работал?Хорошо, получил справочный тип А, самый подробный.В противном случае vector<vector<int> >(4) указывает на тип ссылки B и т. Д.

. Для этой цели make_fixed_vector работал хорошо, но в целом методика имеет недостатки.В частности, поскольку make_fixed_vector не возвращает истинного типа, его размерность (и) не может быть проверена во время компиляции.Во время выполнения возможны вызовы reserve, resize и push_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 может быть более реалистичным.

0 голосов
/ 23 марта 2011

Если вы счастливы использовать шаблоны в своем коде 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);
}
...