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

C++ - Regarding the scope of dynamic arrays

本文关键字:数组 范围 动态 于动态 C++-      更新时间:2023-10-16

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

然而,当我运行程序时,我得到了一个与范围相关的错误:

错误:未在此作用域中声明"Array"

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

有人能解释一下吗?

if之前声明Array。并且不能将不同类型的数组声明为一个变量,所以我认为应该使用to指针。

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

虽然您是对的,因为您在堆上动态分配了内存,所以在显式删除内存(或程序结束)之前,内存不会释放给系统,但当在中声明的块退出时,指向内存的指针就不在范围内了。因此,如果指针将在块之后使用,则需要在更大的范围内存在。

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

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

如果我正确理解你的意图,你要做的是:根据某些逻辑分配内存来存储intcharn元素,然后在稍后的函数中将该数组作为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;

但无论如何(或第三种),编译器必须知道如何处理您试图处理的数据这一事实是无法解决的。

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

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

安德鲁的另一个不同的代码建议是:

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

然后,您可以按照自己的意愿直接使用if。

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

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