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
传递给函数,但这也不起作用。帮忙?
编辑:我不是试图使用可变大小!请注意,我在任何地方都制作了SIZE
和const
!我只想使用相同的 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 expression
与 const
无关(至少没有那么多);)。
假设我们是编译器并面对这个函数:
void foo(const int SIZE)
const
merely 表示“我们无法更改函数体内的函数局部变量 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 ++:在函数内声明数组时,表达式必须具有常量值[重复]的主要内容,如果未能解决你的问题,请参考以下文章