const int*,const int*const和int const*之间有什么区别?

1262 c c++ int pointers const

我总是搞砸了怎么用const int*,const int * constint const *正确的.是否有一套规则来定义您能做什么和不能做什么?

我想知道在任务,传递到职能等方面所做的所有事情和所有不应做的事情.

Mat*_*ice 2097

向后读(由顺时针/螺旋规则驱动):

  • int* - 指向int的指针
  • int const * - 指向const int的指针
  • int * const - const指向int的指针
  • int const * const - const指向const int的指针

现在第一个const可以在类型的任何一侧,所以:

  • 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 int* foo;
int *const bar; //note, you actually need to set the pointer 
                //here because you can't change it later ;)
Run Code Online (Sandbox Code Playgroud)

foo是一个指向常量整数的变量指针.这使您可以更改指向的内容,但不能更改指向的值.大多数情况下会看到C风格的字符串,其中有一个指向a的指针const char.您可以更改指向的字符串,但不能更改这些字符串的内容.当字符串本身位于程序的数据段中且不应更改时,这很重要.

bar是一个指向可以更改的值的常量或固定指针.这就像没有额外语法糖的参考.因为这个事实,通常你会使用一个你将使用T* const指针的引用,除非你需要允许NULL指针.

  • 我想附加一条经验法则,它可以帮助你记住如何发现'const'是否适用于指针或指向数据:将语句拆分为asterix符号,然后,如果const关键字出现在左侧部分(如'const int*foo') - 它属于尖头数据,如果它在右边部分('int*const bar') - 它是关于指针的. (453认同)
  • @Michael:感谢迈克尔这样一个记住/理解const规则的简单规则. (12认同)
  • +1,虽然更好的总结是:**向后读指针声明**,这意味着,接近@Michael的声明:在*first*星号处停止正常的从左到右的读数. (11认同)
  • @Jeffrey:只要没有括号,向后读它就会很好.然后,好吧...... [使用typedef](http://cdecl.ridiculousfish.com/?q=int+%28*+%28*v0%29%28int+%28*%29%28int%29%29%29 %28int%29) (9认同)
  • @gedamial可以,它可以正常工作,但是必须在声明它的同时分配它(因为您不能重新分配“ const指针”)。`const int x = 0; const int * const px =&x; const int * const * const p =&px;`效果很好。 (3认同)
  • 为什么没有C / C ++书以这种方式介绍它?这很棒 (2认同)
  • @JayeshBhoi,不。常量指针的全部要点(没有双关语)是您不能更改其指向的位置!在C和C ++中,这完全独立于指针的值。NULL在这里不会获得任何特殊特权。 (2认同)

Shi*_* Lv 328

对于那些不了解顺时针/螺旋规则的人:从变量的名称开始,顺时针移动(在这种情况下,向后移动)到下一个指针类型.重复直到表达结束.

这是一个演示:

指向int的指针

const指向int const的指针

指向int const的指针

指向const int的指针

const指向int的指针

  • @Jan复杂示例的链接没有权限.你可以直接在这里发布,或删除查看限制吗? (8认同)
  • @Rog它以前拥有所有开放访问权限...不幸的是,我没有写文章,也没有自己的访问权限.但是,这是一篇仍然有效的文章的存档版本:http://archive.is/SsfMX (8认同)
  • 复杂的例子仍然是从右到左,但包括通常的方式解决括号.整个顺时针旋转的东西并没有使这更容易. (7认同)
  • 我喜欢这些颜色。*一个简单的人经过* (5认同)
  • 除了提到的事实之外,螺旋形状只是误导性的,为什么第二个示例中的“* const”用*一种*颜色着色,但在第五个示例中用*两种*颜色着色,在后者中它仍然被解释作为“常量指针”?颜色到底有什么意义? (4认同)
  • 不要依赖这条规则.这不是普遍的.在某些情况下,它会失败. (3认同)
  • 最终示例:来自archive.is/SsfMX的`void(* signal(int,void(* fp)(int)))(int);` (2认同)
  • @hackks自然地,当左边有东西时它会起作用。所以如果你想写像“const int”这样的东西,那么const就取第一个右边的值......所以规则是“如果有的话,就取第一个左边的值,否则就取第一个右边的值” (2认同)

Kaz*_*gon 140

我想这里已经回答了所有问题,但我只想补充一点,你应该小心typedefs!它们不仅仅是文本替换.

例如:

typedef char *ASTRING;
const ASTRING astring;
Run Code Online (Sandbox Code Playgroud)

类型astringchar * const,而不是const char *.这是我总是倾向于放在const类型右侧的一个原因,而不是从一开始.

  • 对我而言,这是永远不会输入指针的原因.我没有看到像`typedef int*PINT'这样的好处(我假设它来自C中的实践并且许多开发人员继续这样做).好的,我用'P`替换了`*`,它不会加快打字速度,再加上你提到的问题. (19认同)
  • @Mephane`PINT`确实是一个相当愚蠢的typedef用法,特别是因为它让我觉得系统商店使用啤酒作为记忆.但是,typedef对于处理函数指针非常有用. (6认同)
  • @KazDragon感谢!没有它,我会搞砸Win32 api中所有那些类型化的'PVOID`,`LPTSTR`东西! (5认同)
  • @Mephane - 我可以看到。然而,对我来说,为了继续使用特殊的语法规则(关于“const”放置),而不是避免使用特殊的语法规则,这样你就可以安全地使用这个语言特性,这似乎有点倒退. (2认同)
  • @Mephane:在使用某些传统宏时,我必须使用pSomething几次,这些宏被编写为接受类型,但如果类型不是单个字母数字标识符,则会分解.:) (2认同)

luk*_*uke 51

几乎所有人都指出:

有什么区别const X* p,X* const pconst X* const p

你必须从右到左阅读指针声明.

  • const X* p 表示"p指向一个常数为X的X":不能通过p更改X对象.

  • X* const p 表示"p是指向非const的X的const指针":您不能更改指针p本身,但可以通过p更改X对象.

  • const X* const p 表示"p是指向X的常量指针":您不能更改指针p本身,也不能通过p更改X对象.

  • 不要忘记`const X * p;`==`X const * p;`,如“ p指向X是const”:不能通过p更改X对象。 (3认同)

小智 47

  1. 常量参考:

    对变量(此处为int)的引用,它是常量.我们主要将变量作为引用传递,因为引用的大小小于实际值,但是存在副作用,这是因为它就像实际变量的别名.我们可能会通过完全访问别名来意外更改主变量,因此我们将其设置为常量以防止此副作用.

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
    
    Run Code Online (Sandbox Code Playgroud)
  2. 常量指针

    一旦常量指针指向变量,它就不能指向任何其他变量.

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
    
    Run Code Online (Sandbox Code Playgroud)
  3. 指向常数的指针

    一个指针,通过它可以不改变它指向的变量的值,这个指针称为指向常量的指针.

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
    
    Run Code Online (Sandbox Code Playgroud)
  4. 指向常量的常量指针

    指向常量的常量指针是一个指针,既不能改变它指向的地址,也不能改变保存在该地址的值.

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error
    
    Run Code Online (Sandbox Code Playgroud)


APr*_*mer 19

一般规则是const关键字立即适用于它之前的内容.例外,一个起点const适用于以下内容.

  • const int*int const*"指向常量int"的意思相同.
  • const int* constint const* const"指向常量int的常量指针"相同.

编辑: 对于Dos和Don'ts,如果这个答案还不够,你能更准确地了解你想要的吗?


T.E*_*.D. 18

这个问题恰恰说明了为什么我喜欢按照我在问题中提到的方式做事,因为类型id可以接受?

简而言之,我发现记住规则的最简单方法是"const" 它适用的东西之后.所以在你的问题中,"int const*"意味着int是常量,而"int*const"意味着指针是常量.

如果有人决定把它放在最前面(例如:"const int*"),作为一种特殊的例外情况,它适用于它后面的东西.

许多人喜欢使用这个特殊的例外,因为他们认为它看起来更好.我不喜欢它,因为它是一个例外,因此混淆了事情.

  • 我对这个问题很感兴趣.逻辑上它是有道理的.然而,大多数c ++开发人员会编写`const T*`并且它变得更自然.无论如何你经常使用`T*const`,通常参考就可以了.当我想要一个`boost :: shared_ptr <const T>`而不是编写`const boost :: shared_ptr <T>`时,我得到了所有这一切.在略有不同的背景下的相同问题. (2认同)

ufu*_*gun 17

简单使用'const'

最简单的用法是声明一个命名常量.为此,我们声明一个常量,好像它是一个变量,但在它之前加上'const'.必须立即在构造函数中初始化它,因为当然,之后无法设置值,因为这会改变它.例如,

const int Constant1=96; 
Run Code Online (Sandbox Code Playgroud)

将创建一个整数常量,无法想象地称为"Constant1",值为96.

这些常量对于程序中使用的参数很有用,但在编译程序后不需要更改.对于程序员而言,它优于C预处理器'#define'命令,因为编译器本身可以理解和使用它,而不是在到达主编译器之前由预处理器替换为程序文本,因此错误消息更有帮助.

它也适用于指针但是必须要小心'const'来确定指针或它指向的是否是常量或两者.例如,

const int * Constant2 
Run Code Online (Sandbox Code Playgroud)

声明Constant2是指向常量整数的变量指针

int const * Constant2
Run Code Online (Sandbox Code Playgroud)

是一种替代语法,它做同样的事情,而

int * const Constant3
Run Code Online (Sandbox Code Playgroud)

声明Constant3是一个指向变量integer的常量指针

int const * const Constant4
Run Code Online (Sandbox Code Playgroud)

声明Constant4是指向常量整数的常量指针.基本上'const'适用于其左边的任何东西(除非没有任何东西,在这种情况下它适用于它的直接权利).

参考:http://duramecho.com/ComputerInformation/WhyHowCppConst.html


rgk*_*rgk 8

在我遇到C++大师Scott Meyers的这本书之前,我有同样的疑问.请参阅本书中的第三个项目,其中详细介绍了如何使用const.

请遵循这个建议

  1. 如果这个词const出现在星号的左边,那么指向的是不变的
  2. 如果单词const出现在星号的右侧,则指针本身是常量
  3. 如果const双方都出现,两者都是不变的


Abh*_*ahu 7

这很简单但很棘手.请注意,我们可以交换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 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这里的指针是只读的,因此声明和定义应该在同一个地方.


小智 7

以简单的方式记住:

如果 const 在 * 之前,则值是常量。

如果 const 在 * 之后,则地址是常量。

如果 const 在 * 之前和之后都可用,则值和地址都是常量。

例如

  1. int * 常量变量;//这里地址是常量。

  2. int const * var;//这里的值是常量。

  3. int const * const var;// 值和地址都是常量。


Jef*_*ges 6

在C++中还有很多其他关于const正确性的细微之处.我想这里的问题只是关于C,但我会给出一些相关的例子,因为标签是C++:

  • 您经常传递像字符串TYPE const &这样的大型参数,以防止对象被修改或复制.示例:

    TYPE& TYPE::operator=(const TYPE &rhs) { ... return *this; }

    但是TYPE & const没有意义,因为引用总是const.

  • 您应该始终标记不修改类的类方法const,否则您无法从TYPE const &引用中调用该方法.示例:

    bool TYPE::operator==(const TYPE &rhs) const { ... }

  • 常见的情况是返回值和方法都应该是const.示例:

    const TYPE TYPE::operator+(const TYPE &rhs) const { ... }

    实际上,const方法不能将内部类数据作为引用返回非const.

  • 因此,必须经常使用const重载创建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 &参考也可能见证它在其他地方被改变的价值.


Che*_*Alf 6

原始设计者反复将C和C++声明语法描述为失败的实验.

相反,让我们将类型命名为"指向Type"; 我会称之为Ptr_:

template< class Type >
using Ptr_ = Type*;
Run Code Online (Sandbox Code Playgroud)

现在Ptr_<char>是一个指针char.

Ptr_<const char>是一个指针const char.

并且const Ptr_<const char>是一个const指针const char.

那里.

在此输入图像描述

  • 你有第一句话的引用吗? (3认同)
  • @Stargateur:显然你已经阅读了上述评论,发现了一些可以用来迂腐的东西.祝你好运.无论如何,像我这样的老人记得很多,如果不进行非常耗时的研究,我们就无法证明这一点.你可以接受我的话. (3认同)
  • @Stargateur [*“Sethi (...) 观察到,如果间接运算符被视为后缀运算符而不是前缀,则许多嵌套声明和表达式会变得更简单,但到那时更改已为时已晚。”* ](https://www.bell-labs.com/usr/dmr/www/chist.html) 来自 DMR。当然,DMR 并没有发明 const 和 volatile 关键字,它们来自 C++ / X3J11,如该页面所示。 (2认同)

小智 5

两侧带有 int 的 const 将指向常量 int

const int *ptr=&i;
Run Code Online (Sandbox Code Playgroud)

或者:

int const *ptr=&i;
Run Code Online (Sandbox Code Playgroud)

constafter*将使常量指针指向 int

int *const ptr=&i;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,所有这些都是指向常量 integer 的指针,但这些都不是常量指针:

 const int *ptr1=&i, *ptr2=&j;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,所有都是指向常量 integer 的指针,ptr2 是指向常量 integer 的常量指针。但 ptr1 不是常量指针:

int const *ptr1=&i, *const ptr2=&j;
Run Code Online (Sandbox Code Playgroud)


小智 5

对我而言,const即相对于左侧或右侧出现还是相对于左侧和右侧出现的位置*有助于我弄清实际含义。

  1. constLEFT的A *表示指针所指向的const对象是对象。

  2. constRIGHT的A *表示指针是const指针。

下表摘自Stanford CS106L标准C ++编程实验室课程阅读器。

在此处输入图片说明