const int *,const int * const和int const *之间有什么区别?
我总是搞砸如何正确使用const int*
, const int * const
和int const *
。 有一套规则定义你可以做什么,不可以做什么?
我想知道所有的事情,所有的事情,任务,职能等等。
向后读(由顺时针/螺旋规则驱动)…
-
int*
– 指向int的指针 -
int const *
– 指向const int的指针 -
int * const
– const指向int的指针 -
int const * const
– 指向const int的const指针
现在第一个const可以在这个types的任何一边:
-
const int *
==int const *
-
const int * const
==int const * const
如果你想疯狂,你可以做这样的事情:
-
int **
– 指向int **
指针的指针 -
int ** const
– 一个指向int的指针的const指针 -
int * const *
– 一个指向一个int的const指针的指针 -
int const **
– 一个指向const int指针的指针 -
int * const * const
– 一个指向int * const * const
的常量指针的const指针 - …
并确保我们清楚const的含义
const int* foo; int *const bar; //note, you actually need to set the pointer //here because you can't change it later ;)
foo
是一个常量int的variables指针。 这可以让你改变你指向的内容,而不是你指向的值。 大多数情况下,你可以看到你有一个指向const char
cstrings。 您可以更改指向哪个string,但不能更改这些string的内容。 当string本身位于程序的数据段中时,这一点很重要,不应该改变。
bar
是一个常量或固定的指针,可以改变一个值。 这就像没有额外语法糖的参考。 由于这个事实,除非需要允许空指针,否则通常使用T* const
指针的引用。
对于那些不了解顺时针/螺旋规则的人:从variables的名字开始,顺时针移动(在这种情况下,向后移动)到下一个指针或types 。 重复,直到expression结束。
这里是一个演示:
我想所有的东西都已经在这里回答了,但是我只想补充一点,你应该小心typedefs! 他们不只是文字replace。 例如:
typedef char *ASTRING; const ASTRING astring;
astring
的types是char * const
,而不是const char *
。 这是我总是倾向于将const放在types右侧的原因之一,从不在开始。
几乎每个人都指出:
const X* p
, X* const p
和const X* const p
之间的区别是什么?
您必须从右向左读取指针声明。
const X* p
意思是“p指向一个X是const”:X对象不能通过p来改变。
X* const p
表示“p是一个非常量X的常量指针”:你不能改变指针p本身,但是你可以通过p改变X对象。
const X* const p
意思是“p是一个常量指针X的const指针”:你不能改变指针p本身,也不能通过p改变X对象。
-
常量引用:
对一个variables(这里是int)的引用,它是常量。 我们主要将variables作为参考传递,因为引用的大小比实际值小,但是有一个副作用,那就是因为它就像是实际variables的别名。 我们可能通过完全访问别名来意外地改变主variables,所以我们使其不变以防止这种副作用。
int var0 = 0; const int &ptr1 = var0; ptr1 = 8; // Error var0 = 6; // OK
-
常量指针
一旦一个常量指针指向一个variables,那么它就不能指向任何其他variables。
int var1 = 1; int var2 = 0; int *const ptr2 = &var1; ptr2 = &var2; // Error
-
指向常量
一个不能改变它所指向的variables的值的指针被称为常量指针。
int const * ptr3 = &var2; *ptr3 = 4; // Error
-
常量指针
指向常量的常量指针不能改变指向的地址,也不能改变保存在该地址的值。
int var3 = 0; int var4 = 0; const int * const ptr4 = &var3; *ptr4 = 1; // Error ptr4 = &var4; // Error
简单的使用'const'
最简单的用法是声明一个命名常量。 要做到这一点,一个声明一个常量,就好像它是一个variables,但在它之前添加“const”。 一个人必须立即在构造函数中初始化它,因为当然,之后的值将不会被修改。 例如,
const int Constant1=96;
会创build一个整型常量,其值为96,被简单地称为“Constant1”。
这些常量对程序中使用的参数非常有用,但在程序编译后不需要改变。 它对程序员来说比C预处理程序的“#define”命令更有优势,因为编译器自己可以理解并使用它,而不是在到达主编译器之前用预处理程序代入程序文本,所以错误消息更有帮助。
它也适用于指针,但必须注意“const”的位置,以确定指针或指向的是常量还是两者。 例如,
const int * Constant2
声明Constant2是指向一个常量整数的variables指针
int const * Constant2
是一个可替代的语法,但是
int * const Constant3
声明Constant3是一个指向variables整数的常量指针
int const * const Constant4
声明Constant4是一个常量指针。 基本上,“const”适用于它的左边的任何东西(除了在这种情况下什么都不适用于它的直接权利)。
ref: http : //duramecho.com/ComputerInformation/WhyHowCppConst.html
这个问题正好说明了为什么我喜欢在我的问题中提到的方法是可以接受的typesid之后的const?
总之,我发现记住规则的最简单的方法是“const”符合它所适用的东西。 所以在你的问题中,“int const *”意味着int是常量,而“int * const”意味着指针是常量。
如果有人决定把它放在最前面(例如:“const int *”),作为一个特殊的例外,在这种情况下它适用于后面的东西。
许多人喜欢使用这种特殊的例外,因为他们认为它看起来更好。 我不喜欢它,因为它是一个例外,从而混淆事物。
规则是“const”适用于立即之前。 例外,一个开始const适用于后面的。
-
const int*
与int const*
相同,意思是“指向常量int的指针”。 -
const int* const
与int const* const
相同,意思是“指向常量int的常量指针”
编辑:对于做和不做,如果这个答案是不够的,你能更准确地说你想要什么?
我有同样的疑问,直到我遇到了C ++大师Scott Meyers的这本书 。 请参阅本书中的第三项,详细介绍如何使用const
。
只要按照这个build议
- 如果
const
字出现在星号左边,那么指向的是常量 - 如果
const
字出现在星号的右边,那么指针本身是不变的 - 如果
const
出现在两边,都是恒定的
在C ++中,围绕const正确性还有许多其他细节。 我想这里的问题只是关于C,但我会给一些相关的例子,因为标签是C ++:
-
你经常像String那样传递大的参数,例如
TYPE const &
它可以防止对象被修改或复制。 例如:TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }
但
TYPE & const
是无意义的,因为引用总是const。 -
您应该始终将不修改类的类方法标记为
const
,否则您不能从TYPE const &
reference调用该方法。 例如:bool TYPE::operator==(const TYPE &rhs) const { ... }
-
常见的情况是返回值和方法都是const。 例如:
const TYPE TYPE::operator+(const TYPE &rhs) const { ... }
事实上,const方法不能返回内部类的数据作为非const的引用。
-
因此,必须经常使用const重载创build一个const和一个非const方法。 例如,如果你定义
T const& operator[] (unsigned i) const;
,那么你可能也会想要非const的版本:inline T& operator[] (unsigned i) { return const_cast<char&>( static_cast<const TYPE&>(*this)[](i) ); }
Afaik,C中没有const函数,非成员函数在C ++中本身不能是const,const方法可能有副作用,编译器不能使用const函数来避免重复的函数调用。 实际上,即使是一个简单的int const &
reference,也可以见证它引用的值在其他地方被改变。
这很简单,但棘手。 请注意,我们可以将const
限定符与任何数据types( int
, char
, float
等)进行交换。
我们来看下面的例子。
const int *p
==> *p
是只读的[ p
是指向常量整数的指针]
int const *p
==> *p
是只读的[ p
是指向常量整数的指针]
int *p const
==> 错误的语句。 编译器引发语法错误。
int *const p
==> p
是只读的[ p
是指向整数的常量指针]。 由于指针p
在这里是只读的,所以声明和定义应该在同一个地方。
const int *p const
==> 错误的语句。 编译器引发语法错误。
const int const *p
==> *p
是只读的
const int *const p1
==> *p
和p
是只读的[ p
是指向常量整数的常量指针]。 由于指针p
在这里是只读的,所以声明和定义应该在同一个地方。
int const *p const
==> 错误的语句。 编译器引发语法错误。
int const int *p
==> 错误的语句。 编译器引发语法错误。
int const const *p
==> *p
是只读的,相当于int const *p
int const *const p
==> *p
和p
是只读的[ p
是指向常量整数的常量指针]。 由于指针p
在这里是只读的,所以声明和定义应该在同一个地方。
C和C ++声明的语法被原始devise者反复描述为一个失败的实验。
相反,让我们将types指向“types指针”; 我会叫它Ptr_
:
template< class Type > using Ptr_ = Type*;
现在Ptr_<char>
是一个指向char
的指针。
Ptr_<const char>
是一个指向const char
的指针。
而const Ptr_<const char>
是一个const char
指针。
那里。