使用 ptr-to-ptr 数组?

Use of ptr-to-ptr array?

这样的东西有什么用处和解释?:

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 没有自己的数组,否则我会理解它,因为我读到这个:The correct way to initialize a dynamic pointer to a multidimensional array?

教授们正在休假,再多说几句。

指针数组有很多用途。

  1. 正在重新排序。假设您要对数组中的对象重新排序。处理指针比移动整个对象快得多。
  2. 动态分配。您可以单独删除或分配每个对象。
  3. 重新分配和性能。假设您想增加数组的大小。重新分配实际对象可能会导致不同类型的问题(无效)。然而,重新分配指针数组或多或少没有问题,而且速度也快得多。

基本思想是它允许您创建一个 "array of arrays"。与矩阵相比,它有一个狭窄的优势,因为它允许您拥有不同大小的子数组,但缺点是所有对象的内存在整个数组中不再连续。

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-capacity 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;