2016-08-16 2 views
1

Что такое использование и объяснение что-то вроде этого ?:Использование массива ptr-to-ptr?

int capacity; 
int** number; 
this->number = new int*[this->capacity]; 

Я учусь на экзамен и в тестовом экзамене они поставили требование использования объекта указатель на указатель и делает динамический массив из него. Есть два класса; Кошелек & WalletKeeper. В решениях, которые они сделали это в заголовочном-файле WalletKeeper:

private: 
    Wallet** wallets; 
    int capacity; 
    int size; 
    /*other stuff below this*/ 

И в конструкторе:

WalletKeeper::WalletKeeper(int capacity) 
{ 
    this->capacity = capacity; 
    this->size = 0; 
    this->wallets = new Wallet*[this->capacity]; 
    this->initiate(); 
} 

Я понимаю, основной динамический массив так:

Wallet * wallets = new Wallet[capacity]; 

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

Кошелек не имеет массив своей собственной, я бы понял это иначе, потому что я прочитал это: The correct way to initialize a dynamic pointer to a multidimensional array?

Профессора не в отпуске до дальнейших проволочек.

+0

Почему бы вам когда-нибудь сделать массив массивов, которые могут содержать другие массивы? Например, матрица может быть представлена ​​как массив массивов (массив чисел для каждой строки, вся матрица - всего лишь массив строк). – ForceBru

+6

Я работаю над ответом, но прежде чем я это сделаю, я просто хочу выразить, насколько я потрясен, что профессора все еще учат C++, как это. Им следовало бы научить вас просто использовать объект 'std :: vector ' или 'std :: vector >', любой из которых был бы бесконечно предпочтительнее этого подверженного ошибкам и плохого соответствия, для практического применения. – Xirema

+1

Это массив кошелек *. Это не «естественный» современный C++, и его следует выполнять с помощью классов контейнеров, и, как это возможно, следует избегать необработанного распределения памяти. – crashmstr

ответ

1

Основная идея заключается в том, что он позволяет создавать «массив массивов». Он имеет узкое преимущество над матрицей в том, что он позволяет иметь под-массивы по-разному, но недостатком является то, что память всех объектов больше не смежна по всему массиву.

Wallet ** w_ptr_ptr = new Wallet*[capacity]; 
for(int i = 0; i < capacity; i++) { 
    w_ptr_ptr[i] = new Wallet[i+1]; 
} 

for(int i = 0; i < capacity; i++) { 
    for(int j = 0; j < i+1; j++) { 
     w_ptr_ptr[i][j] = Wallet(/*...*/); 
    } 
} 

Обратите внимание, что в этом коде, w_ptr_ptr[0] имеет массив разного размера, чем w_ptr_ptr[1].

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

std::vector<std::vector<Wallet>> wallets; 

for(int i = 0; i < capacity; i++) { 
    wallets.emplace_back(i+1); //Will automatically create a i+1-sized array. 
} 

for(int i = 0; i < wallets.size(); i++) { //Note I'm able to query the size here! 
    for(int j = 0; j < wallets[i].size(); j++) { //Again I can query the size! 
     wallets[i][j] = Wallet(/*...*/); 
    } 
} 
+0

Не видя больше кода, мы не можем предположить, что он предназначен для того, чтобы быть массивом массивов «Кошелька» или просто массивом «Кошелька». Для меня более разумно, что они намереваются 'WalletKeeper' держать' Wallet * '. – crashmstr

+0

@crashmstr Ну, случай таков, что есть только ptr2ptr (Кошелек **), указывающий на массив указателей (Кошелек *), и они нигде не указывают. Вот почему я в замешательстве, я бы это понял, если все они указывали на массив каждый. –

+0

Затем код будет присвоить или добавить «новый кошелек» указателям в качестве более позднего шага. «Причина» для этого заключается в том, что вы не выделяете объекты «Кошелька» спереди. Вам нужно будет инициализировать массив до «nullptr», чтобы быть в безопасности (и может проверить, занят ли слот). – crashmstr

3

Существует много применений массивов указателей.

  1. Переопределение. Предположим, вы хотите изменить порядок объектов в массиве. Работа с указателями намного быстрее, чем перемещение всего объекта.
  2. Динамическое распределение. Вы можете удалять или выделять каждый объект по отдельности.
  3. Перераспределение и производительность. Предположим, вы хотите увеличить размер массива. Перераспределение фактических объектов может привести к различным типам проблем (аннулирование). Однако перераспределение массива указателей более или менее безопасно и также намного быстрее.
+0

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

0

Указатель указателей-объектов является часто используемым для матриц реализации ,Действительно, как указатели на объекты реализовать динамический массив, как вы предложили в вашем вопросе:

Wallet* wallets = new Wallet[capacity]; 

делает бумажники указывает первое местоположение массива в Num емкости Wallet объекта.

[Wallet-obj] [Wallet-obj] [Wallet-obj] ... [Wallet-obj] 
    0   1    2   capacity - 1 

Указатель указателей, как:

Wallet** wallets = new Wallet*[capacity]; 

Создание массива Wallet указатель:

[Wallet-pointer] [Wallet-pointer] [Wallet-pointer] ... [Wallet-pointer] 
     0    1     2    capacity-1 

Каждый указатель на вектор должен указывать на динамический массив.

Я попытаюсь «нарисовать» представление:

[0][wallet-pointer] ----> [0][wallet obj] [1][wallet obj] ... [capacity-1][wallet obj] 
[1][wallet-pointer] ----> [0][wallet obj] [1][wallet obj] ... [capacity-1][wallet obj] 
... 
[capacity-1][wallet-pointer] ----> [0][wallet obj] [1][wallet obj] ... [capacity-1][wallet obj] 

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

wallets[0][2]; 

Это означает, что доступ к 1-й указатель в массиве указателя, используя 1 "строку" доступа к объекту 3-го объекта этой строки.

Так как вы можете создать изображение, у вас есть матрица, потому что у вас есть динамический массив n-capacity, например n-capacity rows.

Примечание

При создании экземпляра массива указателей, вы должны инициализировать каждый из них. Это полный код:

Wallet** wallets = new Wallet*[capacity]; 

// Now for each pointer you have to allocate a dynamic array of n-elements. 
for (size_t i = 0; i < capacity; ++i) { 
    wallets[i] = new Wallet[capacity]; 
} 

И то же самое для фазы Deallocation:

// First of all, deallocate each object in each dynamic array: 
for (size_t i = 0; i < capacity; ++i) { 
    delete[] wallets[i]; // wallets[i] is a dynamic array to deallocate 
} 

// Finally deallocate the dynamic array of poiter 
delete[] wallets; 
Смежные вопросы