我总是搞砸如何正确使用const int*、const int*const和int const*。有没有一套规则来定义你能做什么和不能做什么?
我想知道在赋值、传递给函数等方面的所有注意事项。
我总是搞砸如何正确使用const int*、const int*const和int const*。有没有一套规则来定义你能做什么和不能做什么?
我想知道在赋值、传递给函数等方面的所有注意事项。
当前回答
这很简单,但很棘手。请注意,我们可以将const限定符应用于任何数据类型(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 p==>*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是只读的,所以声明和定义应该在同一位置。
其他回答
对于那些不了解顺时针/螺旋规律的人:从变量的名称开始,顺时针移动(在这种情况下,向后移动)到下一个指针或类型。重复此操作,直到表达式结束。
下面是一个演示:
这个问题确切地说明了为什么我喜欢用我在问题中提到的在类型id可接受之后是常量的方式做事?
简而言之,我发现记住这个规则最简单的方法是“const”跟在它应用的对象后面。所以在你的问题中,“int const*”表示int是常量,而“int*const”表示指针是常量。
如果有人决定把它放在最前面(例如:“constint*”),作为这种情况下的一个特殊例外,它适用于后面的东西。
许多人喜欢使用这个特殊的例外,因为他们认为它看起来更好。我不喜欢它,因为它是一个例外,从而混淆了事情。
这主要涉及第二行:最佳实践、分配、功能参数等。
一般做法。尽可能使一切保持稳定。或者换一种说法,从一开始就让所有的常量都是常量,然后完全删除允许程序运行所需的最小常量集。这将大大有助于实现常量正确性,并有助于确保在人们尝试分配不应该修改的内容时不会引入细微的错误。
避免像瘟疫一样的const_cast<>。它有一两个合法的使用案例,但它们非常少。如果你试图改变一个常量对象,你会做得更好,找到第一步中声明它常量的人,并与他们讨论此事,以就应该发生的事情达成共识。
这很好地引导到作业中。只有当它是非常量时,才能将其赋值。如果您想分配给常量,请参见上文。请记住,在声明中int const*foo;和int*const bar;不同的东西是恒定的——这里的其他答案都很好地涵盖了这个问题,所以我就不赘述了。
功能参数:
传递值:例如,voidfunc(int-param),在调用站点,你不在乎这一种方式或另一种方式。可以这样做,即存在将函数声明为void func(int const param)的用例,但这对调用方没有影响,只对函数本身没有影响,因为函数在调用期间不能更改传递的任何值。
通过引用传递:例如,void func(int¶m)现在它确实起了作用。正如刚才声明的,func可以更改参数,任何调用站点都应该准备好处理结果。将声明更改为void func(int const¶m)将更改约定,并保证func现在不能更改param,这意味着传入的内容将返回。正如其他人所指出的,这对于便宜地传递不想更改的大型对象非常有用。传递引用比按值传递大型对象要便宜得多。
传递指针:例如,void func(int*param)和void func(int const*param)这两个与它们的引用对应项几乎同义,但需要注意的是,被调用的函数现在需要检查nullptr,除非其他契约保证func不会在param中收到nullpter。
关于这个话题的评论文章。在这种情况下证明正确性非常困难,犯错误太容易了。所以不要冒险,总是检查指针参数的nullptr。从长远来看,你会让自己免于痛苦和痛苦,并且很难找到bug。至于检查的成本,它非常便宜,在编译器中内置的静态分析可以管理它的情况下,优化器无论如何都会取消它。为MSVC启用“链接时间代码生成”,或为GCC启用“WOPR(我认为)”,您将在程序范围内获得它,即即使在跨越源代码模块边界的函数调用中。
在一天结束时,以上所有内容都证明了一个非常可靠的理由,即总是倾向于引用指针。他们只是更安全。
很多人都答对了,我会在这里整理好,并在给出的答案中添加一些缺失的额外信息。
Const是C语言中的关键字,也称为限定符。Const罐应用于任何变量的声明,以指定其值不会改变
const int a=3,b;
a=4; // give error
b=5; // give error as b is also const int
you have to intialize while declaring itself as no way to assign
it afterwards.
如何阅读?
只需从右到左阅读每一条语句即可顺利完成
3件主要事情
type a. p is ptr to const int
type b. p is const ptr to int
type c. p is const ptr to const int
[错误]
if * comes before int
两种类型
1. const int *
2. const const int *
我们先看
主要类型1。常量int*
在3个地方安排3件事的方法3=6.
i.*开始时
*const int p [Error]
*int const p [Error]
二。开始时常量
const int *p type a. p is ptr to const int
const *int p [Error]
iii.开始时int
int const *p type a.
int * const p type b. p is const ptr to int
主要类型2。常量常量int*
在4个地方安排4件事情的方法,其中2件是相同的4件/2!=12
i.*开始时
* int const const p [Error]
* const int const p [Error]
* const const int p [Error]
二。开始时为int
int const const *p type a. p is ptr to const int
int const * const p type c. p is const ptr to const int
int * const const p type b. p is const ptr to int
iii.启动时的常量
const const int *p type a.
const const * int p [Error]
const int const *p type a.
const int * const p type c.
const * int const p [Error]
const * const int p [Error]
挤成一体
类型a.p是常量int(5)的指针
const int *p
int const *p
int const const *p
const const int *p
const int const *p
类型b.p是int(2)的常量指针
int * const p
int * const const p;
类型c.p是const ptr到const int(2)
int const * const p
const int * const p
只是很少的计算
1. const int * p total arrangemets (6) [Errors] (3)
2. const const int * p total arrangemets (12) [Errors] (6)
小小的额外
int常量*p,p2;
here p is ptr to const int (type a.)
but p2 is just const int please note that it is not ptr
int*常量p,p2;
similarly
here p is const ptr to int (type b.)
but p2 is just int not even cost int
int常量*常量p,p2;
here p is const ptr to const int (type c.)
but p2 is just const int.
完成了
我想这里已经回答了所有问题,但我只想补充一点,你应该小心typedefs!它们不仅仅是文本替换。
例如:
typedef char *ASTRING;
const ASTRING astring;
跨接的类型是char*const,而不是const char*。这是我总是倾向于将常量放在类型的右边,而从不放在开头的原因之一。