我想知道在 C++ 中是否有办法检查动态数组的值是否确实存在。
int *x = new int[5];
好的,所以我认为默认情况下 x 的每个值都是 0。但是,问题是,当我用值填充它时,我实际上可能会输入 0。因此,这会导致混淆,告诉我们如果value 是否真的存在(0 似乎是告诉我们它是 NULL 的成语,但在这种特殊情况下,我不能使用该成语,因为 0 可能是给我的值)。
是否有另一种方法来检查动态数组中的值是否未定义?
好吧,首先,正如乔纳森所说,不能保证数组将被初始化为0
. 您可以单独初始化它,也可以使用int *x = new int[5]();
which 为您进行初始化。
至于你怎么知道哪些是有效的。最简单的方法是存储 struct 而不是int
s。像这样的东西:
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
基本上,为元素分配一个整数值,将自动将其标记为有效。尽管在这个特定示例中,我没有演示如何将值“取消设置”回“无效”。这对于您的用例或编码风格可能有意义,也可能没有意义,只是一些值得深思的东西。
如果它是动态分配的,它不会为你归零;您必须通过将所有条目设置为某个默认值来自己初始化数组。如果零是有效条目,则考虑使用负一。如果所有正值和负值都是有效条目,则考虑使用包含整数值和初始化为 false 的布尔标志的结构。
在 C 中,这将是:
typedef struct {
bool valid;
int value;
} node;
node x[] = new node[5];
如果您不能牺牲一个值,例如最小的负数或最大的正数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;
}
由于正确管理资源涉及许多复杂性,我不会为这项工作使用动态数组。在我看来,你应该看一下std::vector
,这会使你的代码变成这样的东西:
#include <vector>
...
std::vector<int> x();
x.resize(5);
现在,这将使您不再担心资源管理是个婊子,而是专注于真正重要的事情(即处理您的 Xses)。
如果您要使用的它们的值将是密集/连续的,请使用std::vector
(其size()
成员会告诉您当前有效的项目数)。如果值稀疏,请std::set
改用。
无论哪种方式,你最好忘记它的new T[size]
存在,更不用说让自己陷入实际使用它的疯狂。
但是,问题是当我用值填充它时,我实际上可能会输入 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。
不是您构建该数组的方式;数组中没有一个int
s 被初始化。它们可能有任何价值。通常,当您在“调试”模式下构建时,内存会自动为您初始化为零,但这不是 C++ 指定的。
除了我的其他答案之外,如果您认为有效索引将是 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
,或者我的原始答案。