выделение указателей на массив фиксированного размера - PullRequest
2 голосов
/ 11 октября 2011

У меня есть 2 сомнения относительно основ использования указателей.

Со следующим кодом

 int (*p_b)[10];
 p_b = new int[3][10];
 // ..do my stuff
 delete [] p_b

p_b указывает на массив из 3 элементов, каждый из которых имеет длину фиксированного размера 10int.

Q1:

Как объявить p_b, если я хочу, чтобы каждый элемент был указателем на фиксированный размер массива?По сути, я хочу следующее

  p_b[0] = pointer to a fixed-array size of 10
  p_b[1] = pointer to a fixed-array size of 10
  // ... and so on

Я думал о int (** p_b)[10], но тогда я не знаю, как использовать new для его выделения?Я хотел бы избежать возврата к более общему int** p_b

Q2:

В соответствии с моим исходным примером кода выше, как вызывать new, чтобы p_b указывал на уникальный массив фиксированного размераиз 10 int кроме звонка p_b = new int[1][10] ?Чтобы освободить память, мне нужно позвонить delete[], пока я не могу найти выражение, в котором я могу вызвать только просто delete.

Ответы [ 6 ]

2 голосов
/ 11 октября 2011

p_b указывает на массив из 3 элементов, каждый из которых имеет фиксированную длину 10 int.

Как объявить p_b, если я хочу, чтобы каждый элемент был указателем нафиксированный размер массива?

Разве ваше первое предложение не полностью охватывает этот вопрос?

В соответствии с моим исходным примером кода выше, как вызвать new, чтобы p_b указывалуникальный массив фиксированного размера в 10 int кроме вызова p_b = new int[1][10]?Чтобы освободить память, мне нужно позвонить delete[], пока я не могу найти выражение, в котором я могу вызвать только простое удаление.

Я совершенно не понимаю, почему это проблема, но вы могли бы сделать это с помощьюоборачивая ваш массив в другой тип ... скажем std::array, boost::array или std::vector.

1 голос
/ 11 октября 2011

Вот пример того, как реализовать Q1:

int main()
{
    typedef int foo[10];

    foo* f = new foo[3];

    f[0][5] = 5;
    f[2][7] = 10;

    delete [] f;
}

Что касается Q2, единственный способ удалить память, выделенную с новым [], - это удалить [].Если вы лично не хотите писать delete [], вы можете использовать вектор или другой контейнер STL.Действительно, если это не какая-то жесткая убер-оптимизация, вы все равно должны использовать векторы.Никогда не управляйте памятью вручную, если только вы не обязаны это делать.

1 голос
/ 11 октября 2011

Прежде всего, если ваше выражение new имеет квадратные скобки (new somtype[somesize]), ваше delete также должно иметь квадратные скобки (delete [] your_pointer).

Во-вторых, сейчас вы определили p_b как один указатель на некоторые данные. Если вы действительно хотите массив указателей, то вам нужно определить его как массив. Поскольку вы, очевидно, хотите три независимых массива, вам придется распределять каждый из них по отдельности. Вероятно, проще всего, если вы начнете с typedef:

typedef int *p_int;
p_int p_b[3];

Тогда вы выделите три массива:

for (int i=0; i<3; i++)
    p_b[i] = new int[10];

Чтобы удалить их, вам нужно удалить каждый из них отдельно:

for (int i=0; i<3; i++)
    delete [] p_b[i];

Я определенно согласен с @Tomalak, что вам никогда не придется возиться с подобными вещами. Непонятно, чего вы действительно хотите достичь, но все же довольно легко догадаться, что вполне вероятно, что стандартный контейнер в любом случае будет более простым и чистым способом сделать это.

0 голосов
/ 16 июня 2017

На самом деле, никто не отправил ответ на ваш точный вопрос, пока.

Вместо

int (*p_arr)[10] = new int[3][10];
// use, then don't forget to delete[]
delete[] p_arr;

Я предлагаю использовать

std::vector<std::array<int, 10>> vec_of_arr(3);

или если вам не нужно перемещать его и не требуется длительность выполнения:

std::array<std::array<int, 10>, 3> arr_of_arr;

Q1

Как объявить p_b, если я хочу, чтобы каждый элемент был указателем на фиксированный размер массива?

int(**pp_arr)[10] = new std::add_pointer_t<int[10]>[3];
for (int i = 0; i < 3; ++i)
    pp_arr[i] = new int[1][10];
// use, then don't forget to delete[]
for (int i = 0; i < 3; ++i)
    delete[] pp_arr[i];
delete[] pp_arr;

Современный вариант этого кода

std::vector<std::unique_ptr<std::array<int, 10>>> vec_of_p_arr(3);
for (auto& p_arr : vec_of_p_arr)
    p_arr = std::make_unique<std::array<int, 10>>();

или если вам не нужно перемещать его и не требуется длительность выполнения:

std::array<std::unique_ptr<std::array<int, 10>>, 3> arr_of_p_arr;
for (auto& p_arr : arr_of_p_arr)
    p_arr = std::make_unique<std::array<int, 10>>();

Q2

В моем примере исходного кода выше, как вызывать new, чтобы p_b указывал на уникальный массив фиксированного размера, равный 10 int, кроме вызова p_b = new int[1][10]?

Не без переноса массива в другой тип.

std::array<int, 10>* p_arr = new std::array<int, 10>;
// use, then don't forget to delete
delete p_arr;

Вы можете заменить std::array<int, 10> на ваш любимый тип переноса массива, , но вы не можете заменить его псевдонимом массива фиксированного размера . Современный вариант этого кода:

auto p_arr = std::make_unique<std::array<int, 10>>();
0 голосов
/ 11 октября 2011

Для Q1, я думаю, вы хотите

int (*p[3])[10];

Попробуйте cdecl , если вы не уверены.

На ваш другой вопрос, похоже, хорошо отвечают другие ответы.

С уважением, Яти Сагаде

0 голосов
/ 11 октября 2011

Чтобы использовать необработанный указатель для управления двумерным массивом, сначала необходимо создать указатель на указатель на тип элемента массива, который будет указывать на каждую строку массива.Затем каждый указатель строки должен быть назначен фактическим элементам массива для этой строки.

int main()
{
  int **p;

  // declare an array of 3 pointers
  p = new int*[3];

  // declare an array of 10 ints pointed to by each pointer
  for( int i = 0; i < 3; ++i ) {
    p[i] = new int[10];
  }

  // use array as p[i][j]

  // delete each array of ints
  for( int i = 0; i < 3; ++i ) {
    delete[] p[i];
  }

  // delete array of pointers
  delete[] p;
}

Гораздо более простым решением является использование std::array.Если ваш компилятор не предоставляет этот класс, вы также можете использовать std::vector.

std::array<std::array<int,10>,3> myArr; 
myArr[0][0] = 1;
...