2

私は C++ で、int の配列の末尾からゼロを削除するメソッドを書いている学生です。配列は構造体にあり、構造体には配列の長さを追跡する int もあります。

このメソッドは、最初のゼロ以外の要素に遭遇するまで、最後の要素から始めて各要素を調べ、長さの値を変更することによってその要素を「最後の要素」としてマークします。次に、メソッドは元の「最後の要素」に戻り、範囲外ではない要素 (ゼロ) を削除します。

i配列の更新された長さよりも大きい場合に配列内の th 要素を削除する部分はi、次のようになります。

if (i > p->length - 1) {
  delete (p->elems + i); // free ith elem

しかし、その行は間違っています。Delete はポインターを受け取ります。iしたがって、削除したい整数のメモリ位置を取得するには、配列へのポインターを回復してから追加する必要があると感じています。

私の直感は間違っていますか?エラーは微妙ですか?それとも、私は完全に間違った考えを持っていますか? 私は疑問に思い始めました: 本当にこれらのプリミティブを解放する必要があるのでしょうか? それらがプリミティブでない場合、私はそうする必要があります。

4

2 に答える 2

5

私は完全に間違った考えを持っていますか?

残念ながらそのようですね。

new[]配列を割り当てるために 1 つの呼び出しを行う場合は、配列delete[]を解放するために 1 つの呼び出しを行う必要があります。

int *p = new int[10];
...
delete[] p;

配列が構造体にあり、構造体を割り当てるために 1 つの呼び出しを行う場合は、それを解放するために 1 つの呼び出しを行う必要があります。

struct Foo {
    int data[10];
};

Foo *foo = new Foo;
...
delete foo;

配列の一部を解放する方法はありません。

int[10]配列は、実際に10 個の整数が1行に並んでいます (つまり、32 ビット システムでは 40 バイトのメモリに、おそらくオーバーヘッドが加わることになります)。配列に格納されている整数はそのメモリを占有します。それら自体はメモリ割り当てではなく、解放する必要はありません。

つまり、可変長配列が必要な場合は次のようになります。

それが std::vector の目的です

#include <vector>
#include <iostream>

struct Foo {
    std::vector<int> vec;
};

int main() {
    Foo foo;

    // no need for a separate length: the current length of the vector is
    std::cout << foo.vec.size() << "\n";

    // change the size of the vector to 10 (fills with 0)
    foo.vec.resize(10);

    // change the size of the vector to 7, discarding the last 3 elements
    foo.vec.resize(7);
}
于 2010-10-29T23:39:58.837 に答える
3

p->elemsがポインタの場合、ポインタも同様ですp->elems + i(操作が定義されていると仮定します。つまり、 i は整数型です) - そしてp->elems + i == &p->elems[i]

とにかく、int の配列から int を削除したくない (そして削除できない) 可能性が最も高いです (動的または自動的に割り当てられます)。あれは

int* ptr = new int[10];
delete &ptr[5]; // WRONG!

それは単にあなたができないことです。ただし、構造体に配列の長さが含まれている場合、構造体に含まれる長さ情報を変更した後、配列が「サイズ変更された」と考えることができます。結局のところ、ポインターが指す配列のサイズを知る方法はありません。

ただし、配列が整数へのポインターの配列 ( int*[]) であり、これらのポインターが動的に割り当てられたメモリを指している場合は、はい、単一のアイテムを削除でき、コードの行に沿ってそれを実行できます (コードはほとんど表示されません)。正確にするのは難しい)。

于 2010-10-29T23:27:19.460 に答える