首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++:表达式在函数中声明数组时必须有一个常量值

C++:表达式在函数中声明数组时必须有一个常量值
EN

Stack Overflow用户
提问于 2016-05-24 22:25:03
回答 4查看 15.4K关注 0票数 1

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

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

代码语言:javascript
运行
复制
int* Mode(int* numbers, int & mode, const int SIZE)
 {
     int occurences[SIZE];

     // Calcualte mode
 }

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

我的函数调用(主)如下所示:

代码语言:javascript
运行
复制
int* occurencesPtr = Mode(numbersPtr, mode, SIZE);

SIZE定义在文字20的开头。

我理解这个错误是因为函数的SIZE版本只有在函数被调用(?)时才获得它的值,但我不知道如何解决这个问题。

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

编辑:我是而不是尝试使用可变大小!!请注意,我已经将SIZE 变成了 const everywhere!我只想使用相同的大小常数来声明我的数组.

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-05-24 22:45:11

关于const的含义,这里有一种误解,可能是因为这样做的效果有点混乱:

代码语言:javascript
运行
复制
const int SIZE = 20;
int array[SIZE];

但这并不是:

代码语言:javascript
运行
复制
void foo(const int SIZE) {
    int array[SIZE];
    // ...
}

const int SIZE = 20;
foo(SIZE);

问题是数组声明中的数组大小必须是核心常量表达式。简化,这意味着在编译时可以计算的表达式为常量。在第一种情况下(您可以看到SIZE是积分常量20),这是正确的,但在第二种情况下则不是这样。在那里,SIZE函数参数只是const --也就是说它是不可修改的--而不是核心常量表达式。您可以看到不同之处,我可以用一些在运行时之前显然不知道的东西调用foo()

代码语言:javascript
运行
复制
int x;
if (std::cin >> x) {
    foo(x);
}

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

代码语言:javascript
运行
复制
template <int SIZE>
void foo() { ... }

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

或者:

代码语言:javascript
运行
复制
template <int SIZE>
void foo(std::integral_constant<int, SIZE > ) { ... }

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

或者让SIZE成为全局常量,或者让foo()以一种与其参数无关的方式访问它。

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

代码语言:javascript
运行
复制
void foo(const int SIZE) {
    std::vector<int> v(SIZE);
    ...
}
票数 9
EN

Stack Overflow用户

发布于 2016-05-24 22:43:29

我理解这个错误是因为函数的大小版本只在函数被调用(?)时才获得它的值,但是我不知道如何解决这个问题。

选项1

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

代码语言:javascript
运行
复制
constexpr int getSize()
{
   return 20;
}

int* Mode(int* numbers, int & mode)
{
   int occurences[getSize()];

   // ...

}

选项2

使用std::vector代替数组。

代码语言:javascript
运行
复制
int* Mode(int* numbers, int & mode, int size)
{
   std::vector<int> occurences[size];

   // ...

}

选项3

使用函数模板。

代码语言:javascript
运行
复制
template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)
{
   int occurences[SIZE];

   // ...

}

选项4

使用函数模板和std::array

代码语言:javascript
运行
复制
template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)
{
   std::array<int, SIZE> occurences;

   // ...

}
票数 5
EN

Stack Overflow用户

发布于 2016-05-24 22:44:39

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

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

代码语言:javascript
运行
复制
void foo(const int SIZE) { }

const只是说“我们不能改变函数体内的函数局部变量SIZE。我们需要编译它而不假设SIZE是编译时间常数。为什么?”

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

代码语言:javascript
运行
复制
int i{};
std::cin >> i;
foo(i);

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

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

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

代码语言:javascript
运行
复制
template<std::size_t N>
void foo()
{
    std::array<int, N> occurences;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37424899

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档