以下代码行编译得很好并且表现得很好:
list<const int *> int_pointers; // (1)
以下两行不是:
typedef int * IntPtr;
list<const IntPtr> int_pointers; // (2)
我得到完全相同的编译错误
list<int * const> int_pointers; // (3)
我很清楚最后一行不合法,因为STL容器的元素需要可分配。为什么编译器解释(2)与(3)相同?
答案 0 :(得分:9)
简短回答:
const(和volatile)应该在它们符合条件的类型之后自然出现。 以前编写时,编译器会自动在内部重写它:
const int *
变为
int const *
是指向常量int的指针。这些列表将编译正常,因为指针本身仍可分配。
答案 1 :(得分:8)
您从右到左阅读C风格的声明。所以“const int *”是一个指向常量int的指针(“const int”和“int const”意思相同)。那些是完全可分配的。但是(2)和(3)是int的常量指针,因此不可赋值。
答案 2 :(得分:6)
您问“为什么编译器解释(2)与(3)相同?”。好吧,因为在C ++语言(以及C语言)中,它们在语义上是相同的。将typename定义为
时typedef int *IntPtr;
然后,类型const IntPtr
将代表int *const
,而不代表const int *
。这就是typedef-names在C ++中的工作方式。
C ++中的Typedef-names不是宏。虽然他们没有定义新类型(只是现有类型的别名),但结果别名仍然是“原子”,“单片”,在某种意义上,应用于别名的任何限定符都将应用为顶级资格赛。当你使用typedef-name时,没有办法“潜入”const限定符,以便它以某种方式“下降”到类型的低级部分(在你的情况下为int
)。
如果你坚持使用typedef-names,你没有其他的直接选择,只能提供两个不同的typedef-names,比如
typedef int *IntPtr;
typedef const int *ConstIntPtr;
并在需要类型的指针到const版本时使用ConstIntPtr
。
答案 3 :(得分:5)
const IntPtr
和const int*
不是一回事。
1)const int*
是“指向const int
”的指针。
2)const IntPtr
展开为int * const
(想象(int *) const
),这是“const
指向int
”的指针。
简而言之,typedef
就像一组括号。您无法更改const
指针所指向的typedef
- 。
答案 4 :(得分:3)
const int *
与写int const *
相同,意味着非常量指针指向的常量值。
使用typedef将指针本身定义为常量,就像在第3个语句中一样。
答案 5 :(得分:0)
我相信您知道const IntPtr
和IntPtr const
属于同一类型。
这意味着list<const IntPtr>
和list<IntPtr const>
属于同一类型。
这意味着您正在尝试编译它:
typedef int * IntPtr;
list<IntPtr const> int_pointers; // (2bis)