Какая польза и объяснение чего-то подобного?
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];
Это будет означать, что вы создадите указатель, указывающий на место в памяти, где создается этот массив кошельков, чтобы вы могли изменить содержимое этих слотов памяти.
Но зачем вам указатель на массив указателей? Какая польза?
Бумажник не имеет собственного массива, я бы понял это иначе, потому что я прочитал это: Правильный способ инициализации динамического указателя на многомерный массив?
Профессора в отпуске до дальнейших церемоний.
Основная идея заключается в том, что он позволяет вам создавать «массив массивов». Он имеет узкое преимущество перед матрицей в том, что он позволяет вам иметь подразборы различного размера, но недостаток в том, что память всех объектов больше не является смежной по всему массиву.
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(/*...*/);
}
}
Есть много применений массивов указателей.
Указатель на указатели-объекты обычно используется для матрицы реализация. Действительно, как указатели на объекты реализуют динамический массив, как вы предложили в своем вопросе:
Wallet* wallets = new Wallet[capacity];
заставляет кошельки указывать первое местоположение массива на num -acity Wallet
объект.
[Wallet-obj] [Wallet-obj] [Wallet-obj] ... [Wallet-obj]
0 1 2 capacity - 1
Указатель указателей, таких как:
Wallet** wallets = new Wallet*[capacity];
Создать массив Указатель кошелька:
[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-емкостью, такой как строки с n-емкостью.
Когда вы создаете массив указателей, вы должны инициализировать каждый из них.
Это полный код:
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];
}
И то же самое для фазы освобождения:
// 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;