我有一个关于动态数组范围的快速问题,我认为这会导致我正在编写的程序中出现错误。此片段检查函数参数并分支到第一个或第二个,具体取决于用户传递的内容。
但是,当我运行程序时,我收到与范围相关的错误:
error: ‘Array’ was not declared in this scope
除非我对C ++的了解失败,否则我知道在分支完成时,条件内创建的变量会超出范围。但是,我动态分配了这些数组,所以我无法理解为什么我不能在程序中稍后操作数组,因为指针应该保留。
//Prepare to store integers
if (flag == 1) {
int *Array;
Array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char *Array;
Array = new char[input.length()];
}
任何人都可以对此有所了解吗?
答案 0 :(得分:5)
在Array
之前声明if
。并且你不能将不同类型的数组声明为一个变量,所以我认为你应该使用指针。
int *char_array = nullptr;
int *int_array = nullptr;
//Prepare to store integers
if (flag == 1) {
int_array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char_array = new char[input.length()];
}
if (char_array)
{
//do something with char_array
}
else if (int_array)
{
//do something with int_array
}
同样,当j_random_hacker指向时,您可能希望更改程序设计以避免批量if
答案 1 :(得分:3)
虽然你是正确的,因为你在堆上动态分配它们,但是在你明确删除它(或程序结束),指针之前,内存将不会被释放到系统中。当在退出时声明它的块时,内存超出范围。因此,如果指针在块之后使用,则指针需要存在于更宽的范围内。
答案 2 :(得分:3)
内存仍然分配(即占用宝贵的空间),在结束}
之后无法访问它,因为此时程序失去了解决它的能力。为避免这种情况,您需要将new[]
返回的指针分配给在外部作用域中声明的指针变量。
作为一个单独的问题,看起来好像你正试图分配两种不同类型之一的内存。如果你想以便携式方式执行此操作,则必须使用void *
来保存指针,或者(不太常见)使用包含每种类型指针的union
类型。无论哪种方式,您都需要维护状态信息,以便程序知道已进行了哪种分配。 通常,想要这样做表明设计不佳,因为每次访问都需要切换此状态信息。
答案 3 :(得分:2)
如果我理解你的意图正确你想要做的是:根据一些逻辑分配内存来存储{em} n 元素int
或char
然后在您的函数中访问该数组为int
或char
,而无需单个if
语句。
如果上述理解是正确的,那么简单的答案是:“C ++是一种强类型语言,你想要的是不可能的。”
然而...... C ++也是一种非常强大而灵活的语言,所以这里可以做的就是:
<强>铸造即可。如下所示:
void * Array;
if(flag1) Array = new int[len]
else Array = new char[len];
// ... later in the function
if(flag) // access as int array
int i = ((int*)Array)[0];
是的,这很丑陋,你必须在功能周围撒上if
个。所以这里有一个替代方案:模板
template<class T> T foo(size_t _len)
{
T* Array = new T[_len];
T element = Array[0];
return element;
}
另一种更为模糊的做事方式可能是使用union
:
union int_or_char {int i; char c;};
int_or_char *Array = new int_or_char[len];
if(flag) // access as int
int element = Array[0].i;
但是,不管怎样,编译器必须知道如何处理您尝试使用的数据。
答案 4 :(得分:1)
Turix的回答是对的。你需要记住,这里分配了两件事,数组的内存和存储数组位置时的内存。
因此,即使数组中的内存是从堆中分配的,并且可用于需要的代码,存储数组位置的内存(Array变量)也会在堆栈中分配,并且一旦超出范围就会丢失。在这种情况下,if块结束时。你甚至不能在同一个if的else部分使用它。
Andrew提出的另一个不同的代码建议是:
void *Array = nullptr;
if (flag == 1) {
Array = new int[input.length()];
} else if (flag == 2) {
Array = new char[input.length()];
}
然后你可以按照你的意愿直接使用。
这部分我不确定:如果你想知道它是一个int还是char,你可以使用typeid文字。不起作用,至少我可以'让它发挥作用。
或者,您可以使用flag变量来猜测它的类型。