Выделение mem с использованием new вместо malloc - PullRequest
0 голосов
/ 20 марта 2019

Я пытаюсь найти точный эквивалент этого кода, используя new вместо malloc.Указатель на указатель на массив с плавающей точкой [4]: ​​

float (**f)[4] = (float(**)[4])malloc(2 * sizeof(float(*)[4]));
for (int p = 0; p < 2; p++) {
    f[p] = (float(*)[4])malloc(3 * sizeof(float[4]));
}

Я пробовал несколько комбинаций, но не могу найти правильный синтаксис.

float (**f)[4] = new ...

Ответы [ 3 ]

1 голос
/ 20 марта 2019

Вы можете создать вспомогательный класс, который может new автоматически подойти вам автоматически с помощью преобразования.

template <unsigned N = 0> struct NewAny;

template <unsigned N> struct NewAny {
    template <typename T>
    operator T * () const { return new T[N]; }
};

template <> struct NewAny<0> {
    template <typename T>
    operator T * () const { return new T; }
};

int main () {
    float (**x)[4] = NewAny<2>();
    delete[] x;
    x = NewAny<>();
    delete x;
}

В вашем примере:

float (**f)[4] = NewAny<2>();
for (int p = 0; p < 2; p++) {
    f[p] = NewAny<3>();
}

Современный C ++ учит избегать подверженной ошибкам природы ручного управления динамически выделяемой памятью с использованием контейнеров и интеллектуальных указателей. Вы можете сделать что-то вроде ниже, чтобы создать D -мерный vector:

template <typename T, unsigned D> struct Vectorate;

template <unsigned N, typename T, unsigned D>
struct Vectorate<T[N], D> {
    typedef
    typename Vectorate<std::array<T, N>, D>::type type;
};

template <typename T, unsigned D>
struct Vectorate {
    typedef
    typename Vectorate<std::vector<T>, D-1>::type type;
};

template <typename T>
struct Vectorate<T, 0> {
    typedef T type;
};

В вашем примере:

Vectorate<float[4], 2>::type f;
f.resize(2);
for(auto &ff : f) ff.resize(3);
1 голос
/ 20 марта 2019

Обычная старая декларация (не делайте этого):

try
{
    float *** f = new float ** [2];
    for (size_t i = 0; i < 2; i++)
    {
       f[i] = new float * [3];
       for (size_t j = 0; j < 3; j++)
           f[i][j] = new float[4];
    }
} catch(const std::exception & e) { /* This is a pain to deal with to avoid any leak */ }

// Now you can access via f[0][1][2]
// delete[] in reverse order.

Немного лучше (избегайте использования большого количества выделений):

try 
{
    typedef float BigArray[3][4];
    BigArray * f = new BigArray[2];
} catch(const std::exception & e) { /* here it's simple */ }
// delete with delete[] f

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

std::vector<std::vector<std::vector<float>>> f(2, std::vector<std::vector<float>>(3, std::vector<float>(4)));
// Use with f[0][1][2]

Кроме того, как многие сказали бы, вместо указателя на указатель на указатель с плавающей точкой, вместо этого вы должны хранить свой массив в указателе на float, это будет намного эффективнее, так как вам не нужно разыменовывать в 3 шага чтобы получить доступ к элементу, например:

int vectorElems = 4, columns = 3, rows = 2;
int rowStride = vectorElems * columns;  
float * f = new float[rows*columns*vectorElems];
// Access with stride:
f[0 * rowStride + 1 * vectorElems + 2] = 3.14f;

// Delete with delete[] f

Существуют также классы матрицы шаблонов (например, в opencv), которые делают это правильно, предоставляя перегруженный оператор (), чтобы вы могли получить доступ к объекту, например f(0, 1, 2)

0 голосов
/ 20 марта 2019

Я не уверен ... Но попробуйте это:

float **f[4];
    for(int i = 0; i < 4; i++){
        f[i] = (float**)malloc(sizeof(float**));
    }
    printf("%ld", sizeof(f));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...