【问题标题】:initialize array with constant number does not work用常数初始化数组不起作用
【发布时间】:2013-05-31 21:27:39
【问题描述】:

当我使用常量 nVar 而不是数字时,出现以下错误。

constants.h:

extern const unsigned int nVar;

constants.cpp:

#include "constants.h"
const unsigned int nVar = 5;

ma​​in.cpp

#pragma once
#include "constants.h"
void foo(const double q[nVar])
{
    // ...
}

编译器:

数组常量在']'标记之前不是整数常量

在 ',' 标记之前应为 ')'

'const' 之前的预期非限定 ID

【问题讨论】:

    标签: c++ arrays constants


    【解决方案1】:

    我认为这是因为编译器应该在编译时知道数组的大小,但在您的示例中,由于 extern,nVar 的值只有在链接时才能知道

    【讨论】:

    • 正确。将赋值 (=5) 部分移动到头文件中,它将编译得很好——在这种情况下,编译器知道该数组的大小。
    • @parry: 首先= 5不是赋值,是初始化。其次,简单地将= 5 移动到头文件将立即触发 ODR 违规(通常报告为“多定义”链接器错误)。为了能够在头文件中指定= 5,必须为对象提供内部链接,即必须删除extern
    • AndreyT Pedantry 从来都不是我的兴趣 :) 除此之外,编译器在遇到数组时应该知道数组的大小。我相信我们可以信任 OP 将初始化和分配放在正确的位置 - 我并不是建议将其作为最佳实践,只是说明它会使编译器可以看到大小。
    【解决方案2】:

    首先,在我们的示例中,您没有使用常量“初始化”数组。您正在指定数组的大小。请注意,在给定的示例中,无论如何都将忽略数组大小。你的声明

    void foo(const double q[nVar])
    

    实际上等价于

    void foo(const double q[])
    

    void foo(const double *q)
    

    其次,为了使整型常量可以在常量表达式中使用,它必须用初始化器声明。在您的main.cpp 中,您的常量声明时没有初始化,这意味着它不能形成常量表达式,也不能在数组声明器中使用。

    除非你真的需要一个带有外部链接的 const 对象,否则声明你的常量的正确方法是

    const unsigned int nVar = 5;
    

    就在头文件中。注意:没有extern,并且初始化器在头文件中指定。在这种情况下必须删除constants.cpp 中的定义。从技术上讲,这将在每个翻译单元中创建一个具有内部链接的独立 nVar 对象,但除非用作左值,否则它通常不会占用任何内存。

    【讨论】:

    • 这听起来不对,这听起来像是static const 成员变量的规则,但这不适用于const 全局变量,对吗?如果您想将其用作左值,即使static const 也需要在翻译单元中定义。
    • @Mooing Duck:我不确定你想说什么以及它与成员变量有什么关系。带有初始值设定项的命名空间范围变量声明始终是定义,这意味着它已经被定义。无需在翻译单元中定义任何内容。至于仅在常量表达式中使用是否会占用内存 - 这在很大程度上是一个实现质量问题。
    • 我一直认为这会导致 ODR 违规,除非它被标记为 extern
    • @Mooing Duck:在 C++(相对于 C)命名空间范围内 const 对象默认具有内部链接,即普通的 const 等同于 static const。因此,它不会产生 ODR 违规。
    • 哦,从来不知道。我猜是有道理的。
    猜你喜欢
    • 1970-01-01
    • 2015-10-21
    • 1970-01-01
    • 2020-03-10
    • 2012-06-10
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 2020-12-07
    相关资源
    最近更新 更多