1

我有一个关于动态数组范围的快速问题,我认为这会导致我正在编写的程序中出现错误。此代码段检查函数参数并根据用户传递的内容分支到第一个或第二个。

但是,当我运行该程序时,我得到一个与范围相关的错误:

错误:未在此范围内声明“数组”

除非我对 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()];
            }

任何人都可以对此有所了解吗?

4

5 回答 5

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

于 2012-07-19T06:35:31.960 回答
3

虽然您是对的,因为您在堆上动态分配它们,所以在您明确删除它(或程序结束)之前,内存不会释放给系统,指向内存的指针在块时超出范围在 exits 中声明。因此,如果要在块之后使用您的指针,则它们需要存在于更广泛的范围内。

于 2012-07-19T06:39:44.953 回答
3

内存保持分配状态(即占用宝贵的空间),在关闭后无法访问它},因为此时程序失去了解决它的能力。为避免这种情况,您需要将返回的指针分配给new[]在外部作用域中声明的指针变量。

作为一个单独的问题,您似乎正在尝试分配两种不同类型之一的内存。如果您想以可移植的方式执行此操作,则必须使用 avoid *来保存指针,或者(不太常见)union包含每种类型的指针的类型。无论哪种方式,您都需要维护状态信息,让程序知道已经进行了哪种分配。 通常,想要这样做表明设计不佳,因为每次访问都需要打开此状态信息。

于 2012-07-19T06:48:09.720 回答
2

如果我正确理解您的意图,您正在尝试做的是:根据某些逻辑分配内存来存储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在函数周围撒上那些 s。所以这里有一个替代方案:模板

template<class T> T foo(size_t _len)
{
  T* Array = new T[_len];
  T element = Array[0];
  return element;
}

另一种更晦涩的做事方式可能是使用unions:

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;

但是一种或另一种方式(或第三种方式)无法绕过编译器必须知道如何处理您尝试使用的数据的事实。

于 2012-07-19T06:58:11.033 回答
1

Turix 的回答是正确的。您需要记住,这里分配了两件事,数组的内存和存储数组位置时的内存。

因此,即使数组中的内存是从堆中分配的,并且可以在任何需要的地方用于代码,但存储数组位置的内存(数组变量)在堆栈中分配,并且会尽快丢失因为它超出了范围。在这种情况下,当 if 块结束时。你甚至不能在同一个 if 的 else 部分使用它。

我会给出的另一个来自 Andrew 的不同代码建议是:

void *Array = nullptr;

if (flag == 1) {
    Array = new int[input.length()];
} else if (flag == 2) {
    Array = new char[input.length()];
}

然后你可以按照你的意图直接使用 if 。

这部分我不确定:如果您想知道它是 int 还是 char,您可以使用typeid文字。不工作,至少我不能让它工作。

或者,您可以使用标志变量来猜测它是什么类型。

于 2012-07-19T06:49:08.000 回答