C ++:在函数内声明数组时,表达式必须具有常量值[重复]

Posted

技术标签:

【中文标题】C ++:在函数内声明数组时,表达式必须具有常量值[重复]【英文标题】:C++: Expression must have a constant value when declaring array inside function [duplicate] 【发布时间】:2016-09-22 08:03:13 【问题描述】:

我查看了所有其他类似主题的帖子,但没有任何帮助,所以请不要标记为重复。

我在main() 中定义const int SIZE = 20;。然后,我将其作为参数传递给我的函数 Mode:

int* Mode(int* numbers, int & mode, const int SIZE)
 
     int occurences[SIZE];

     // Calcualte mode
 

但是,我得到了错误,expression must have a constant value

我的函数调用(在 main 中)如下所示:

int* occurencesPtr = Mode(numbersPtr, mode, SIZE);

SIZE 被定义在文字 20 的开头。

我了解该错误是因为函数的 SIZE 版本仅在调用函数时获取其值 (?),但我不知道如何解决此问题。

我什至尝试将const int * const SIZEPtr = &SIZE 传递给函数,但这也不起作用。帮忙?

编辑:我不是试图使用可变大小!请注意,我在任何地方都制作了SIZEconst!我只想使用相同的 SIZE 常量来声明我的数组。

编辑:动态数组不是我需要的。我只想要一个普通的命名数组,用传递给函数的 constant 大小值定义。

【问题讨论】:

100% 重复。使用您的确切标题进行搜索。在答案中寻找“动态”。 可变长度数组不是标准 C++。虽然一些编译器支持它们作为扩展,但不能保证在切换到不同的工具链时它会可用。 int *occurrences = new int[SIZE]; .... ;删除(发生); 在标准 C++ 中无法实现您想要的方式。 (原因是new int[SIZE];把数组分配在堆里,而int出现[SIZE];把它分配到栈里(即在函数的局部变量中间)) 【参考方案1】:

const 没有做你认为它在你的 Mode 函数中所做的事情。

当在函数定义中使用const 时,const 只是告诉编译器该函数不会在其函数范围内更改声明为const 的参数。 但这不会使参数成为常量,它实际上称为常量表达式。 一些编译器强制执行此操作,其他编译器不强制执行此操作,因此允许您更改 const 表达式(使用 @ 传递的参数987654327@关键字)。

为了使用可全局访问的常量值,例如SIZE,您需要在调用函数之前声明一个全局常量;可以在main() 之外声明,或者至少在除main() 之外的所有其他函数的范围之外声明,如果您必须在main 中声明所有内容。将全局常量传递给 Mode 函数,就像传递任何其他变量一样。

哦,还有,main() 需要返回类型。

我已编辑代码以满足您的特定限制。

这是您原始代码的变体:

int main()
    //Declare constants first.
    const int SIZE = 20; /*Could declare here instead.*/

    //Declare variables next.
    int *intPtr = 0; // to hold the pointer passed from Mode.
    int *numbersPointer = 0;
    int mode = 0;

    //Define Mode (using OP's code.)
    int* Mode(int* numbers, int & mode, const int size)
        int occurences[size];
         // Calculate mode
    

    /*Now use constants, variables, and functions.*/

    intPtr = Mode(numbersPointer, mode, SIZE); //Call mode.

    return 0;

【讨论】:

谢谢,但是这个程序是用于作业的,我老师的政策是没有全局常量或变量,所以我不能使用它。不过对将来的参考很有用:) 没问题,总是乐于帮助同学!我已经修改了代码以更好地满足您的需求。如果您需要帮助,请 PM 我。 奇怪的是你的老师不允许使用全局常量——这些是安全的。我还没有认识一位老师劝阻他们,即使是在刚开始上课的时候。当然,全局变量是不安全的,如果有的话,应该很少使用。我想请您的老师对全局常量进行一些澄清。 哇哇哇...你是如何在 Main() 中声明一个函数的? 可以(但不推荐)在 C++ 的 main 中声明一个函数。最好在 main 之外声明函数,这样其他函数可以互相访问,但只要所有函数共享同一个作用域,就可以了。【参考方案2】:

这里对const 的含义存在误解,可能是因为它的工作原理有点令人困惑:

const int SIZE = 20;
int array[SIZE];

但这不是:

void foo(const int SIZE) 
    int array[SIZE];
    // ...


const int SIZE = 20;
foo(SIZE);

问题是数组声明中的数组大小必须是核心常量表达式。简而言之,这意味着在编译时可评估为常量的表达式。在第一种情况下是正确的(您可以看到SIZE 是整数常量20)但在第二种情况下不是正确的。在那里,SIZE 函数参数只是const - 从某种意义上说,它是不可修改的 - 而不是核心常量表达式。您可以看到不同之处在于我可以调用 foo() 并使用在运行时之前明显不可知的内容:

int x;
if (std::cin >> x) 
    foo(x);

为了将参数传递给foo,并将该参数用作数组绑定,仅将其设置为const 是不够的 - 必须将实际整数值编码到类型中(除非您将foo() 称为constexpr,我假设这里不是这种情况)。在这种情况下,您必须执行以下操作:

template <int SIZE>
void foo()  ... 

const int SIZE = 20;
foo<SIZE>();

或:

template <int SIZE>
void foo(std::integral_constant<int, SIZE > )  ... 

const int SIZE = 20;
foo(std::integral_constant<int, SIZE> );

或者干脆让SIZE 成为一个全局常量或者foo() 可以通过与它的参数无关的方式访问。


或者,总是有一个简单的选项:使用std::vector

void foo(const int SIZE) 
    std::vector<int> v(SIZE);
    ...

【讨论】:

谢谢,解决了很多问题。我对 C++ 很陌生,实际上我不知道模板是什么或它的作用,但它可以工作:)【参考方案3】:

你把事情弄糊涂了。 constant expressionconst 无关(至少没有那么多);)。

假设我们是编译器并面对这个函数:

void foo(const int SIZE)  

constmerely 表示“我们无法更改函数体内的函数局部变量 SIZE。 我们需要编译它而不假设SIZE 是编译时间常数。为什么?

因为没有人阻止我们做这样的事情:

int i;
std::cin >> i;
foo(i);

您可以将任何(匹配/可转换的)值传递给按值 const 函数参数。

当编译器假定传递给foo 的值是编译时常量表达式时会发生什么?

如果您想传递编译时常量,请使用模板,并在使用时使用 std::array 而不是 T[N]

template<std::size_t N>
void foo()

    std::array<int, N> occurences;

【讨论】:

【参考方案4】:

我了解该错误是因为函数的 SIZE 版本仅在调用函数时获取其值 (?),但我不知道如何解决此问题。

选项 1

不要在main 中定义SIZE,而是添加一个constexpr 函数。使用constexpr 函数而不是传递大小。

constexpr int getSize()

   return 20;


int* Mode(int* numbers, int & mode)

   int occurences[getSize()];

   // ...


选项 2

使用std::vector 代替数组。

int* Mode(int* numbers, int & mode, int size)

   std::vector<int> occurences[size];

   // ...


选项 3

使用函数模板。

template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)

   int occurences[SIZE];

   // ...


选项 4

使用函数模板和std::array

template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)

   std::array<int, SIZE> occurences;

   // ...


【讨论】:

以上是关于C ++:在函数内声明数组时,表达式必须具有常量值[重复]的主要内容,如果未能解决你的问题,请参考以下文章

c语言中形参和实参的区别?

noobSTL-1-配置器-1

关于数组自定义函数的关键点

C++11 学习笔记-类型推导

C++11 学习笔记-类型推导

C语言 main()前可以放哪些限定的函数!?