C ++ - 关于动态数组的范围

时间:2012-07-19 06:34:43

标签: c++ pointers scope

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

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

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()];
            }

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

5 个答案:

答案 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 元素intchar然后在您的函数中访问该数组为intchar,而无需单个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变量来猜测它的类型。