0

C ++で、動的配列の値が実際に存在するかどうかを確認する方法があるかどうか疑問に思いました。

int *x = new int[5];

さて、デフォルトではxのすべての値は0になると思います。しかし、問題は、値を入力するときに実際に0を入力する可能性があることです。したがって、これにより、値が実際に存在するかどうか(0はNULLであることを示すイディオムのようですが、この特定のケースでは、0が私に与えられた値である可能性があるため、そのイディオムを使用できません)。

動的配列の値が未定義かどうかを確認する別の方法はありますか?

4

7 に答える 7

3

まず第一に、Jonathonが言ったように、配列がに初期化されるという保証はありません0。個別に初期化することも、初期化int *x = new int[5]();を行う方法を使用することもできます。

どれが有効かをどうやって知るのか。最も簡単なアプローチは、sの代わりに構造体を格納することintです。このようなもの:

struct T {
    T() : valid(false), value(0) {
    }

    bool valid;
    int  value;
};

T *p = new T[5]; // each element will be initialized to false/0 because T has a constructor.

次に、次のことを実行できます。

p[0].value = 10;
p[0].valid = true;

などなど。

編集: より高度なオプションとして、演算子のオーバーロードを使用して、次のようにvalidフラグを自動的に設定できます。

struct T {
    T() : valid(false), value(0) {
    }

    T &operator=(int x) {
        valid = true;
        value = x;
        return *this;
    }

    bool valid;
    int  value;
};

T *p = new T[5]; // each element will be initialized to false/0 because T has a 
p[1] = 10;       // p[1] is now true/10

基本的に、要素に整数値を割り当てると、要素は自動的に有効としてマークされます。この特定の例では、値を「無効」に「設定解除」する方法を示していません。これは、ユースケースやコーディングスタイルにとって意味がある場合とそうでない場合があります。

于 2012-04-23T01:59:59.207 に答える
2

動的に割り当てられている場合、ゼロ化されることはありません。すべてのエントリをデフォルト値に設定して、配列を自分で初期化する必要があります。ゼロが有効なエントリである場合は、負の値を使用することを検討してください。すべての正の値と負の値が有効なエントリである場合は、整数値を含む構造と、falseに初期化されたブールフラグの使用を検討してください。

Cでは、これは次のようになります。

typedef struct {
    bool valid;
    int  value;
} node;

node x[] = new node[5];
于 2012-04-23T01:55:30.547 に答える
1

最小の負または最大の正などの値を犠牲にしてint「設定されていない」ことを意味することができない場合は、側面に設定されているものを追跡する必要があります。C ++では、次を使用できますstd::vector<bool>

int *x  = new int[5];
std::vector<bool> isSet(5, false);
if (!isSet[3]) {
    x[3] = 123;
    isSet[3] = true;
}
于 2012-04-23T01:58:41.603 に答える
0

使用する値が密集/連続する場合は、を使用しますstd::vector(そのsize()メンバーは、現在有効なアイテムの数を教えてくれます)。値がまばらな場合は、std::set代わりに使用してください。

new T[size]いずれにせよ、実際にそれを使用することの狂気にさらされることは言うまでもなく、それが存在することをまったく忘れたほうがよいでしょう。

于 2012-04-23T02:11:56.223 に答える
0

リソースを適切に管理するには多くの複雑さが伴うため、このジョブには動的配列を使用しません。私の意見では、を覗いてみるとstd::vector、コードが次のようになります。

#include <vector>

...

    std::vector<int> x();
    x.resize(5);

これで、リソース管理が何であるかを心配するのをやめ、実際に重要なこと(つまり、Xsesの処理)に集中することができます。

于 2012-04-23T02:23:21.633 に答える
0

ただし、問題は、値を入力するときに実際に0を入力する可能性があることです。したがって、値が実際に存在するかどうかを判断するのに混乱が生じます。

「0」が実際に存在するかどうかについて混乱はありません。そこに配置しなかった0が配列にある場合、それはまだ存在しています。たまたま配列内にあるゼロと、そこに配置したゼロの間に違いはありません。値を割り当てた要素と初期化されていない要素を区別する必要がある場合は、その情報を別の場所で追跡する必要があります。

bool *b = new bool[5](); // initialize the array to all false
int *x = new int[5]; // don't initialize the array
x[3] = 0; // set the fourth element in the array to 0
b[3] = true; // record that the fourth element in the array has been set

raw配列は使用しないでください。また、 new / deleteは使用しないでください)


int *x = new int[5];

さて、デフォルトではxのすべての値は0になると思います。

その配列を構築する方法ではありません。int配列内のsはどれも初期化されません。それらは任意の値を持つことができます。多くの場合、「デバッグ」モードでビルドすると、メモリは自動的にゼロで初期化されますが、これはC++では指定されていません。

于 2012-04-23T02:32:47.697 に答える
0

私の他の答えに加えて、有効なインデックスがスパースになると思われる場合std::mapの別のアプローチは、次のような連想配列として使用することです。

std::map<int, int> x;
x[0] = 10;
x[2] = 123;
// indexes 0 and 2 are set, the rest do not exist.

値が事前設定されているかどうかをテストするには、次の手順を実行します。

if(x.find(n) != x.end()) {
    // there is a value at index n
} else {
    // no value found at index n
}

有効なインデックスが連続している場合は、、std::vectorまたは私の元の回答を使用することもできます。

于 2012-04-23T04:42:19.317 に答える