Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Указатель на [Указатель на]

446
14 апреля 2013 года
Meander
487 / / 04.09.2011
Здравствуйте.
Можно определить указатель на массив указателей любой размерности
 
Код:
Type   *p;// кратность = 1
Type  **p;// кратность = 2
Type ***p;// кратность = 3
Можно ли параметризовать этот процесс? Например функция принимает в качестве параметра кратность указателя (1, 2, 3 и т.д.). Эта функция должна возвращать объект, тождественный указателю p в примере. Чтобы после выделения памяти под определенное число объектов, на которые будут указывать эти указатели, можно было работать с ними как с массивами, например:
 
Код:
p[i];      // для Type   *p;
p[i][j];   // для Type   **p;
p[i][j][k];// для Type   ***p;
Что то не получается придумать алгоритм такой параметризации.
341
15 апреля 2013 года
Der Meister
874 / / 21.12.2007
Цитата: Meander
Понимаю, что можно определить столько обычных классов, сколько размерностей требуется, просто интересно, позволяет ли C++ решить задачу описанной параметризации?


Код:
template <typename T, int n>
struct Pointer {
    typedef typename Pointer<T, n - 1>::Type *Type;
};

template <typename T>
struct Pointer<T, 1> {
    typedef T *Type;
};

Pointer<int, 2>::Type pointer = new int*[10];
Но лучше давайте не надо.
62K
14 апреля 2013 года
LWhisper
33 / / 27.11.2012
Указатель на указатель на массив указателей в цивилизованном мире называется 3-х мерным массивом (3D-Array, Multi-Dimensional Array) и прекрастно гуглится:

Код:
// Не надо использовать нетипизированные константы (прим. автора ответа)
#define HEIGHT 5
#define WIDTH 3
#define DEPTH 7

int main() {
  double ***p3DArray;

  // Выделение памяти
  p3DArray = new double**[HEIGHT];
  for (int i = 0; i < HEIGHT; ++i) {
    p3DArray[i] = new double*[WIDTH];

    for (int j = 0; j < WIDTH; ++j)
      p3DArray[i][j] = new double[DEPTH];
  }

  // Указание значений
  p3DArray[0][0][0] = 3.6;
  p3DArray[1][2][4] = 4.0;

  // Освобождение памяти
  for (int i = 0; i < HEIGHT; ++i) {
    for (int j = 0; j < WIDTH; ++j)
      delete [] p3DArray[i][j];

    delete [] p3DArray[i];
  }
  delete [] p3DArray;

  return 0;
А теперь объясни, пожалуйста, свой вопрос. Ты хочешь написать функции CreateArray и DeleteArray, которые будут создавать / уничтожать двух, трех, четырехмерным массивы? В принципе, да, можно. Только это бессмысленно, потому что тебе всёравно нужно указывать размерность каждого массива. А значит это будут перегрузки функции:

 
Код:
T* CreateArray(long firstSize)
T** CreateArray(long firstSize, long secondSize)
T*** CreateArray(long firstSize, long secondSize, long thirdSize)
В принципе, тебе никто не запрещает возвращать void* и приводить его к нужному тебе типу. Возможно с шаблонами или генериками из С++11 это можно даже автоматизировать так, чтобы тебе приходил уже типизированный указатель... Но вопрос о том как ты намерен задавать размеры массивов и зачем всё это нужно остаётся в силе.
446
14 апреля 2013 года
Meander
487 / / 04.09.2011
Для указателя
 
Код:
double ***p;
ты показал как задать размеры. Однако, этот указатель можно представить так
 
Код:
typedef double*    p1;
typedef p1*        p2;
typedef p2*        p3;
//создаем переменную типа p3
p3 p;
//для p можно задать размеры как обычно
p1, p2 и p3 - разные типы, порождаются рекурсивно. Вопрос в том как создать некий шаблонный класс с методом возвращающим такого типа объекты. Кратность указателя определяется параметром. Если 1, возвращает объект типа p1, если 2 - p2 и т.д.
Назначение простое. Создать класс (конструктор принимает размерность массива) содержащий переменную выше описанного типа и метод задающий размеры массива по всем измерениям. Если эта переменная открытый член, то обращаться к ней можно как к обычному многомерному массиву. Вот ты привел пример создания трехмерного массива, а если построить описанный мной класс, то создание массива любой размерности было бы короче. Понимаю, что можно определить столько обычных классов, сколько размерностей требуется, просто интересно, позволяет ли C++ решить задачу описанной параметризации?
62K
14 апреля 2013 года
LWhisper
33 / / 27.11.2012
Дорогой автор. в твоём распоряжении язык программирования, позволяющий использовать ассёмблерные вставки. Ты волен стрелять себе в ногу сколько тебе угодно. Возвращай void* и приводи его к тому типу, который тебе нравится. Но сперва ответь на вопрос - зачем? Кому понадобилась сферическая женщина в вакууме? Что ты с ней будешь делать?

Неужели проще написать метод, который расчитывает размеры массива, создать экземпляр фабрики (или синглтонить её), делегировать метод фабрике, вызвать конструктор класса через фабрику?! ЗАЧЕМ?!

Код:
#include "ArrayFactory.hpp"

typedef double* DoubleArray;
typedef double** Double2DArray;
typedef double*** Double3DArray;

int _tmain(int argc, _TCHAR* argv[])
{
    DoubleArray arr1d = ArrayFactory::CreateArray<double>(5);
    Double2DArray arr2d = ArrayFactory::CreateArray<double>(5, 10);
    Double3DArray arr3d = ArrayFactory::CreateArray<double>(5, 10, 28);

    ArrayFactory::DeleteArray<double>(arr1d);
    ArrayFactory::DeleteArray<double>(arr2d);
    ArrayFactory::DeleteArray<double>(arr3d);

    return 0;
}

// ArrayFactory.hpp

#pragma once

class ArrayFactory
{
public:
    template<typename T>
    static T* CreateArray(int x)
    {
        return new T[x];
    }

    template<typename T>
    static T** CreateArray(int y, int x)
    {
        T** result = new T*[y];
        for (int i = 0; i < y; i++)
            result[i] = new T[x];
       
        return result;
    }

    template<typename T>
    static T*** CreateArray(int z, int y, int x)
    {
        T*** result = new T**[z];

        for (int i = 0; i < z; i++)
        {
            result[i] = new T*[y];
            for (int k = 0; k < y; k++)
                result[i][k] = new T[x];
        }
       
        return result;
    }
};
Нужен тебе 4-х мерный массив - напиши ещё метод для создания четырехмерного массива. Если ты на этапе компиляции не знаешь сколько измерений у твоего массива, то что ты вообще собираешься с ним делать?

P.S. И да, как я уже сказал, ты можешь написать метод void* CreateArray(int demensions, delegate) и приводить его результаты к своему типу. Но ты не сможешь заставить компилятор типизировать этот указатель, если demensions расчитываются в процессе работы - как ты себе это представляешь? :)
446
14 апреля 2013 года
Meander
487 / / 04.09.2011
То что хотел в начале не получается, поэтому попробовал так

Код:
#include <iostream>
#include <stdlib.h>

template <class T>
class Array {
  private:
    int  dim,  //число измерений
        *siz; //размеры измерений  
    T   *arr;//главный вектор
  public:
         Array(int,...);
        ~Array(void);
    T&   operator()(int,...);
};


template <class T>
Array<T>::Array(int x,...){
  int *p = &x, i=0, len = 1;
  dim = 0;
  while(*p){
    dim++;
    p++;
  }
  siz = new int [dim];
  while(*p){
    siz[i] = (*p);
    len *= siz[i];
    p++;
    i++;
  }
 
  arr = new T [len];
}

template <class T>
Array<T>::~Array(void){
  delete [] siz; siz  = NULL;
  delete [] arr; arr = NULL;
}

template <class T>
T& Array<T>::operator()(int x,...){
  int k = 0, m = 1, *p = &x, i = 0, l;
  while(*p){
    l = (*p);
    k = k + l * m;
    m = m * siz[i];
    p++;
    i++;
  }
  return arr[k];
}
//1 x
//2 y*X + x
//3 z*X*Y + y*X + x
//4 k*X*Y*Z + z*X*Y + y*X + x
int main(int argc, char *argv[]) {
  int X = 5,
      Y = 2,
      Z = 2;
     
  Array<double> array(X,Y,Z);
 
  for(int x=0;x<X;x++)
    for(int y=0;y<Y;y++)
      for(int z=0;z<Z;z++){
        array(x,y,z) = z*X*Y +y*X + x;
      }

  for(int x=0;x<X;x++)
    for(int y=0;y<Y;y++)
      for(int z=0;z<Z;z++){
        double k = array(x,y,z);
        std::cout << k << '\n';
      }

  system("pause");
    return 0;
}
правда возник трабл с вычислением индексов одномерного массива внутри перегруженного оператора (). Чуть ниже дана последовательность формул для вычисления индексов в зависимости от псевдо-размерности, но запрограммировать пока не получается. Этот код работает неправильно, может еще ошибки есть, в принципе такого рода класс мне подходит. Думаю, что он будет тормозить по сравнению с обычными массивами.
360
14 апреля 2013 года
P*t*
474 / / 15.02.2007
Может что-нибудь вроде этого?

Код:
const int size = 10;

void* createArray(int dim) {
     if (dim==1) return new int[size];
     void* res = new void*[size];
     for (int i=0; i<size; ++i) res[i] = createArray(dim - 1);
     return res;
}

void printArray(void* array) {
     if (typeid(array) == typeid(int*))
           for (int i=0; i<size; ++i) cout << array[i] << endl;
     else
           for (int i=0; i<size; ++i) printArray(array[i]);
}
446
14 апреля 2013 года
Meander
487 / / 04.09.2011
Попробую, правда меня терзают смутные сомнения, что обращение к конкретной ячейке будет мудреным.
446
15 апреля 2013 года
Meander
487 / / 04.09.2011
Цитата: Der Meister

Но лучше давайте не надо.


Почему, ведь теперь можно создавать массив любой размерности одним кликом мыши?

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог