在静态数组声明中两次使用C++ const

10

我之前看过在静态数组的声明中使用了两次const,现在我正在创建自己的静态数组,想知道在某些情况下为什么需要两次使用 const。

如果是一个指针数组,会有什么不同吗?

a. static const TYPE name[5];
b. static const TYPE const name[5];

c. static const TYPE* name[5];
d. static const TYPE* const name[5];

我的理解是,b. 是无效的,但如果使用两次 const 是有效的,那么它的目的是什么?

4个回答

20
const TYPE* x;

这意味着x指向的东西是常量。

TYPE* const x;

意味着指针x是常量。

将它们结合起来,你会得到:

const TYPE* const x;

指针本身和指向的内容都是const。


谢谢您的迅速回复。我明天会将其标记为正确。 - Jim

2

您可以将任何cv限定符(constvolatile)应用于任何类型,包括具有cv限定的类型--但不能在同一声明中使用。然而,它们在优先级方面比任何运算符都更强,并且可以在限定类型的两侧应用:

// Let T by any type:
T const tr;
const T tl;
const T const tlr; // only in C
const const const const const T t5; // only in C
typedef const T CT;
CT const tcc; // fine, although CT was already const

声明完全相同的常量T。如果T已经有cv限定符,那么这不会改变其他资格限定符的含义。

现在,来看看优先级;你可以说“我想要一个指向常量T的指针”:

const T (* tp);

通常写作为:
const T* tp;

因为在任何情况下const的绑定强于*。以相同的方式,您可以定义一个变量,它是“常量但指向可变的T”:

T (* const tp) = 0; // must be initialised, because tp is immutable

通常写作为

T* const tp = 0;

同样地,下标操作符[]也被应用——与表达式中的相同优先级。

0

const在C++ 2003中对同一类型使用两次是非法的,但在C++ 2011中是合法的(参见7.1.6.1 [decl.type.cv]第1段:“冗余的cv限定符将被忽略。”)。当您使用

static const TYPE const name[5];

你两次定义了TYPE常量。然而需要注意的是,在C++ 2011中,这种声明也是非法的,因为在声明时需要初始化一个const对象。其含义是

const TYPE

并且

TYPE const

是完全等价的:在这两种情况下,您都使TYPE对象恒定不变。为了保持一致性,我总是将const放在右边,因为除了顶级类型以外,每个const都必须放在右侧(好吧,除非某些编码指南强制要求不同,但我正在与愚蠢的编码指南作斗争)。

当使用指针时,事情就变得不同了。涉及到两种类型:指向类型的类型和指针。这两种类型可以单独地被做成const

TYPE const*       ptr1(0);  // non-const pointer to const TYPE
TYPE* const       ptr2(0);  // const pointer to non-const TYPE
TYPE const* const ptr3(0);  // const pointer to const TYPE

最好的方法是从右向左阅读类型声明来确定什么是 const。当然,这需要假设 const 限定符被放置在正确的位置。您可以在上述讨论中将 const 替换为 volatileconst volatile,并且相同的推理适用。

0
在第一个代码块中,第二行有一个多余的重复的const,它没有任何作用。(事实上,好的编译器会警告你这个问题。)你正在声明一个由5个const TYPE组成的数组,就是这样。
第二个代码块有两种不同的情况:第一行创建了一个由五个可变指向const TYPE的指针组成的数组,而后者创建了一个由五个常量指向const TYPE的指针组成的数组。
请注意,您必须初始化常量数组:由于您无法在以后更改值,因此定义未初始化的值是没有意义的。

实际上,您可以向类型添加任意多的“const”。它们是幂等的。 - bitmask
@bitmask:哦,好的,已修复。不过,明智的编译器会给你一个警告 :-) 谢谢! - Kerrek SB
哎呀,我可能在这里混淆了C和C++。我的错。 - bitmask
@bitmask:我现在不是完全确定(我认为我的编译器实际上说这是非法的,但我不太想去查找标准参考),所以我已经缓和了措辞。 - Kerrek SB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接