为什么常量指针不能是常量表达式? [英] Why can't a constant pointer be a constant expression?
问题描述
以下程序编译:
template <const int * P>
class Test{};
extern const int var = 42; //extern needed to force external linkage
int main()
{
Test<&var> test;
}
但是,这不是,这让我感到惊讶:
This one, however, doesn't, which is a surprise for me:
template <const int * P>
class Test{};
extern const int var = 42; //extern needed to force external linkage
extern const int * const ptr = &var; //extern needed to force external linkage
int main()
{
Test<ptr> test; //FAIL! Expected constant expression.
}
替代示例:
int main()
{
const int size = 42;
int ok[*&size]; //OK
const int * const pSize = &size;
int fail[*pSize]; //FAIL
}
我已经得出结论,无论指针是否为const并使用常量表达式初始化,指针都不能是常量表达式.
I have concluded that a pointer just can't be a constant expression regardless of whether it's const and initialized with a constant expression.
问题:
- 我的结论正确吗?
- 如果是这样,为什么指针不能是常量表达式?如果没有,为什么上面的程序不能编译?
- C ++ 0x(如果需要,可以使用C ++ 11)更改任何内容吗?
感谢您的见解!
推荐答案
有点复杂.在C ++ 03和C ++ 11中,如果var
是本地静态/类静态或名称空间范围变量,则&var
是常量表达式.这称为地址常量表达式.可以保证在运行任何代码之前(静态初始化阶段)使用该常量表达式初始化类静态或名称空间作用域指针变量,因为它是一个常量表达式.
It's a bit more complicated. In C++03 and C++11, &var
is a constant expression if var
is a local static / class static or namespace scope variable. This is called an address constant expression. Initializing a class static or namespace scope pointer variable with that constant expression is guaranteed to be done before any code is run (static initialization phase), because of it being a constant expression.
但是,仅自C ++ 11起,存储地址&var
的 constexpr 指针变量也可以用作地址常量表达式,并且仅自C ++ 11起,您可以取消引用地址常量表达式(实际上,您甚至可以取消引用-甚至包括本地数组元素地址,但让我们保留其在原位),如果它引用的是在取消引用之前初始化的常量整数变量或constexpr变量,则您将再次获得一个常量表达式(根据类型和值类别的不同,常量表达式的类型可能会有所不同).因此,以下是有效的C ++ 11:
However only since C++11, a constexpr pointer variable that stores the address &var
can also be used as an address constant expression and only since C++11, you can dereference an address constant expression (actually, you can dereference even more - even local array element addresses, but let's keep it ontopic) and if it refers to a constant integral variable initialized prior to the dereference or a constexpr variable, you again get a constant expression (depending on the type and value category, the kind of constant expression may vary). As such, the following is valid C++11:
int const x = 42;
constexpr int const *px = &x;
// both the value of "px" and the value of "*px" are prvalue constant expressions
int array[*px];
int main() { return sizeof(array); }
如果是这样,为什么指针不能为常量表达式?如果没有,为什么上面的程序不能编译?
If so, why can't a pointer be a constant expression? If not, why don't the above programs compile?
这是标准措辞中的已知限制-对于指针类型的模板参数,当前仅允许将其他模板参数用作参数或& object
.即使编译器应该能够做更多的事情.
This is a known limitation in the Standard's wording - it currently only allows other template parameters as arguments or & object
, for a template parameter of pointer type. Even though the compiler should be capable of doing much more.
这篇关于为什么常量指针不能是常量表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!