为什么不是来自常量POD对象常量的字段本身?

时间:2013-03-13 17:40:23

标签: c++ templates

我想专门为某个GUID设计一个模板,这是一个16字节的结构。 GUID对象具有内部链接,因此我不能使用对象本身的地址,但我认为我可以使用对象的内容,因为对象是常量。但这不起作用,如此示例代码所示:

struct S
{
    int const i;
};
S const s = { 42 };
char arr[s.i];

如果是s,为什么s.i不是常量?任何解决方法?

2 个答案:

答案 0 :(得分:7)

struct s的初始化可以在运行时发生。但是,在编译时必须知道数组的大小。编译器不会(确定)知道s.i的值在编译时是已知的,所以它只是看到你正在使用变量来做你不应该做的事情。问题不在于constness,而是需要数组大小的问题。

您可能误解了const的含义。它只意味着在变量初始化之后,它永远不会改变。例如,这是合法的:

void func(int x){
    const int i = x*5; //can't be known at compile-time, but still const
    //int array[i]; //<-- this would be illegal even though i is const 
}

int main(){
    int i;
    std::cin >> i;
    func(i);
    return 0;
}

要解决此限制,在C ++ 11中,您可以将其标记为constexpr,以指示可以在编译时确定该值。这似乎是你想要的。

struct S
{
    int const i;
};
int main(){
    constexpr S const s = { 42 };
    char arr[s.i];
    return 0;
}

编译:

$ c++ -std=c++11 -pedantic file.cpp


在C99中,你正在做的是合法的,在编译时不需要知道数组的大小。

struct S
{
    int const i;
};
int main(){
    struct S const s = { 42 };
    char arr[s.i];
    return 0;
}

编译:

$ cc -std=c99 -pedantic file.c

答案 1 :(得分:2)

至少在大多数情况下,const实际上意味着更接近“只读”而不是“常数”。在C89 / 90中,基本上它的所有意思都是“只读”。 C ++增加了一些可以保持不变的情况,但它仍然一直都没有接近(不幸的是,在非平凡的情况下,跟踪它究竟意味着什么)。

幸运的是,“解决方法”是以几乎可以肯定的方式编写代码:

std::vector<char> arr(s.i);

结论:大多数在C ++中使用内置数组应该被认为是可疑的。您可以从非常量表达式初始化矢量这一事实只是许多优势之一。