0

我想知道在 C++ 中是否有办法检查动态数组的值是否确实存在。

int *x = new int[5];

好的,所以我认为默认情况下 x 的每个值都是 0。但是,问题是,当我用值填充它时,我实际上可能会输入 0。因此,这会导致混淆,告诉我们如果value 是否真的存在(0 似乎是告诉我们它是 NULL 的成语,但在这种特殊情况下,我不能使用该成语,因为 0 可能是给我的值)。

是否有另一种方法来检查动态数组中的值是否未定义?

4

7 回答 7

3

好吧,首先,正如乔纳森所说,不能保证数组将被初始化为0. 您可以单独初始化它,也可以使用int *x = new int[5]();which 为您进行初始化。

至于你怎么知道哪些是有效的。最简单的方法是存储 struct 而不是ints。像这样的东西:

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,这会使你的代码变成这样的东西:

#include <vector>

...

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

现在,这将使您不再担心资源管理是个婊子,而是专注于真正重要的事情(即处理您的 Xses)。

于 2012-04-23T02:23:21.633 回答
0

如果您要使用的它们的值将是密集/连续的,请使用std::vector(其size()成员会告诉您当前有效的项目数)。如果值稀疏,请std::set改用。

无论哪种方式,你最好忘记它的new T[size]存在,更不用说让自己陷入实际使用它的疯狂。

于 2012-04-23T02:11:56.223 回答
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

(注意,你不应该使用原始数组,也不应该使用 new/delete)


int *x = new int[5];

好的,所以我认为默认情况下 x 的每个值都是 0。

不是您构建该数组的方式;数组中没有一个ints 被初始化。它们可能有任何价值。通常,当您在“调试”模式下构建时,内存会自动为您初始化为零,但这不是 C++ 指定的。

于 2012-04-23T02:32:47.697 回答
0

除了我的其他答案之外,如果您认为有效索引将是 sparse,另一种方法是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 回答