我总是搞砸了如何正确使用<code>const int* , const int * constint const * 。 是否有一组规则定义您可以做什么和不能做什么?

我想知道在分配,传递给函数等方面所有需要做的事情。


#1楼

向后读取(受“ 顺时针/螺旋规则”驱动):

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

现在,第一个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指针
  • ...

并确保我们清楚const的含义

const int* foo;
int *const bar; //note, you actually need to set the pointer //here because you can't change it later ;)

foo是指向常量整数的变量指针。 这使您可以更改指向的内容,但不能更改指向的值。 最常见的情况是使用C样式的字符串,其中有指向const char的指针。 您可以更改指向的字符串,但是不能更改这些字符串的内容。 当字符串本身位于程序的数据段中并且不应更改时,这一点很重要。

bar是指向可以更改的值的常量或固定指针。 这就像没有多余语法糖的参考。 由于这个事实,除非需要允许使用NULL指针,否则通常会在使用T* const指针的地方使用引用。


#2楼

一般规则是const关键字适用于紧随其后的内容。 例外,起始const适用于以下内容。

  • const int*int const*相同,表示“指向常量int的指针”
  • const int* constint const* const相同,表示“指向常量int的常量指针”

编辑:对于该做什么和不该做什么,如果这个答案还不够,您能否更精确地知道自己想要什么?


#3楼

简单使用const

最简单的用法是声明一个命名常量。 为此,将一个常量声明为变量,但在其前面加上const 。 一个人必须在构造函数中立即对其进行初始化,因为,当然,一个人以后不能设置该值,因为那会改变它。 例如:

const int Constant1=96;

将创建一个整数常量,其值难以想象地称为Constant1 ,值为96。

此类常数对于程序中使用的参数很有用,但在编译程序后无需更改。 与C预处理程序#define命令相比,它对程序员具有优势,因为它可以被编译器本身理解和使用,而不是在到达主编译器之前被预处理器替换为程序文本,因此错误消息会更有帮助。

它也适用于指针,但必须注意const以确定指针或其指向的对象是常量还是两者。 例如:

const int * Constant2

声明Constant2是指向常量整数的变量指针,并且:

int const * Constant2

是一种替代语法,具有相同的功能,而

int * const Constant3

声明Constant3是指向变量整数的常量指针,并且

int const * const Constant4

声明Constant4是指向常量整数的常量指针。 基本上,“ const”适用于其紧靠左边的任何东西(除非没有什么东西,在这种情况下它适用于其紧靠右边的任何东西)。

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


#4楼

几乎每个人都指出:

const X* pX* const pconst X* const p什么区别?

您必须从右到左读取指针声明。

  • const X* p表示“ p指向X是const”:不能通过p更改X对象。

  • X* const p意思是“ p是指向非const X的const指针”:您不能更改指针p本身,但是可以通过p更改X对象。

  • const X* const p意思是“ p是指向X的const指针,它是const”:您不能更改指针p本身,也不能通过p更改X对象。


#5楼

我认为这里已经回答了所有问题,但是我想补充一下,您应该提防typedef ! 它们不只是文本替换。

例如:

typedef char *ASTRING;
const ASTRING astring;

astring的类型是char * const ,而不是const char * 。 这就是为什么我总是倾向于将const放在类型的右边,而不是从一开始就这样做。


#6楼

这个问题正好说明了为什么我喜欢以我在问题中提到的方式在类型ID可接受之后以const的方式进行操作?

简而言之,我发现记住规则的最简单方法是,将“ const”放在要应用的内容之后 。 因此,在您的问题中,“ int const *”表示int是常量,而“ int * const”将表示指针是常量。

如果有人决定将其放在最前面(例如:“ const int *”),则在这种情况下,它是一个特殊的例外,适用于其后的事物。

许多人喜欢使用该特殊异常,因为他们认为它看起来更好。 我不喜欢它,因为这是一个例外,因此使事情变得混乱。


#7楼

  1. 常数参考:

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

     int var0 = 0; const int &ptr1 = var0; ptr1 = 8; // Error var0 = 6; // OK 
  2. 常量指针

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

     int var1 = 1; int var2 = 0; int *const ptr2 = &var1; ptr2 = &var2; // Error 
  3. 指向常量的指针

    不能更改其指向的变量的值的指针称为常量指针。

     int const * ptr3 = &var2; *ptr3 = 4; // Error 
  4. 指向常量的常量指针

    指向常量的常量指针既不能更改其指向的地址,也不能更改保留在该地址的值的指针。

     int var3 = 0; int var4 = 0; const int * const ptr4 = &var3; *ptr4 = 1; // Error ptr4 = &var4; // Error 

#8楼

简单但棘手。 请注意,我们可以用任何数据类型( intcharfloat等)交换const限定符。

让我们看下面的例子。


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 ==> *pp是只读的[ p是指向常量整数的常量指针]。 由于此处的指针p是只读的,因此声明和定义应位于同一位置。


int const *p const ==> 错误的语句。 编译器将引发语法错误。

int const int *p ==> 错误的语句。 编译器将引发语法错误。

int const const *p ==> *p是只读的,等效于int const *p

int const *const p ==> *pp是只读的[ p是指向常量整数的常量指针]。 由于此处的指针p是只读的,因此声明和定义应位于同一位置。


#9楼

在您遇到C ++专家Scott Meyers的这本书之前,我一直和您有同样的疑问。 请参考本书的第三项,他在其中详细介绍了有关使用const

只要遵循这个建议

  1. 如果const单词出现在星号的左侧,则指向的是常量
  2. 如果单词const出现在星号的右边,则指针本身是常量
  3. 如果const出现在两边,则两者都是常数

#10楼

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

这是一个演示:


#11楼

最初的设计者多次将C和C ++声明语法描述为失败的实验。

相反,让我们将类型命名为“ Type指针”。 我称它为Ptr_

template< class Type >
using Ptr_ = Type*;

现在Ptr_<char>是一个指向char

Ptr_<const char>是指向const char的指针。

const Ptr_<const char>是指向const charconst指针。

那里。


#12楼

这主要涉及第二行:最佳实践,分配,功能参数等。

一般惯例。 尝试使所有内容都成为const 。 或者换种说法,使所有const都以const开头,然后准确删除允许程序运行所需的最少const集。 这将对实现const正确性有很大帮助,并且将有助于确保当人们尝试分配不应修改的内容时,不会引入细微的错误。

避免像瘟疫一样使用const_cast <>。 有一个或两个合法的用例,但它们之间相差无几。 如果您尝试更改const对象,则最好做的是找到谁以第一步声明它为const ,并与他们讨论此事以达成共识。

这非常巧妙地导致了任务。 仅当它是非常量时,才可以分配它。 如果要分配给const,请参见上文。 请记住,在声明中int const *foo;int * const bar; 不同的东西是const -这里的其他答案已经很好地涵盖了这个问题,所以我不再赘述。

功能参数:

按值传递:例如,在调用站点上,您不在乎一种或另一种方式的void func(int param) 。 可以说有一些用例将函数声明为void func(int const param)但对调用方没有影响,仅对函数本身没有影响,因为在此过程中,函数无法更改传递的任何值电话。

通过引用传递:例如void func(int &param)现在确实有所作为。 正如刚刚声明的那样,允许func更改param ,任何调用站点都应准备好处理后果。 将声明更改为void func(int const &param)更改合同,并保证func现在不能更改param ,这意味着传入的内容将返回。 正如其他人指出的那样,这对于廉价传递不想更改的大对象非常有用。 传递引用比按值传递大对象便宜得多。

通过指针传递:例如void func(int *param)void func(int const *param)这两个对象与它们的引用对象几乎是同义的,需要注意的是,除非有其他契约保证,否则被调用函数现在需要检查nullptr确保func它永远不会在param收到nullptr

关于该主题的观点。 在这样的情况下证明正确性是非常困难的,这太容易出错了。 因此,不要冒险,请始终检查nullptr指针参数。 从长远来看,您将避免痛苦和痛苦,并且难以发现错误。 至于检查的成本,它非常便宜,并且在编译器中内置的静态分析可以管理它的情况下,优化器仍然会忽略它。 打开MSVC的链接时间代码生成功能,或者打开GCC的WOPR(我认为)功能,您将在程序范围内实现它,即,即使在跨越源代码模块边界的函数调用中也是如此。

归根结底,上述所有情况都是一个非常可靠的案例,总是喜欢引用指针。 他们只是更安全。


#13楼

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

const int *ptr=&i;

要么:

int const *ptr=&i;

*之后的const将使常量指针指向int

int *const ptr=&i;

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

 const int *ptr1=&i, *ptr2=&j;

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

int const *ptr1=&i, *const ptr2=&j;

#14楼

对我来说, const的位置(即相对于*出现在LEFT或RIGHT还是同时出现在LEFT和RIGHT上)有助于我弄清实际含义。

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

  2. *的RIGHT const表示该指针是const指针。

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


#15楼

只是为了完整起见,请遵循其他说明,对于C ++并不确定。

  • pp-指向指针的指针
  • p-指针
  • 数据-实例中指出的事物x
  • 粗体 -只读变量

指针

  • p数据int *p;
  • p data - int const *p;
  • p数据int * const p;
  • p 数据 int const * const p;

指针指向

  1. pp p数据int **pp;
  2. pp p数据int ** const pp;
  3. pp p数据int * const *pp;
  4. pp p 数据 int const **pp;
  5. pp p数据int * const * const pp;
  6. pp p 数据 int const ** const pp;
  7. pp p 数据 int const * const *pp;
  8. pp p 数据 int const * const * const pp;
// Example 1
int x;
x = 10;
int *p = NULL;
p = &x;
int **pp = NULL;
pp = &p;
printf("%d\n", **pp);// Example 2
int x;
x = 10;
int *p = NULL;
p = &x;
int ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);// Example 3
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);// Example 4
int const x = 10; // Definition must happen during declaration
int const * p = NULL;
p = &x;
int const **pp = NULL;
pp = &p;
printf("%d\n", **pp);// Example 5
int x;
x = 10;
int * const p = &x; // Definition must happen during declaration
int * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);// Example 6
int const x = 10; // Definition must happen during declaration
int const *p = NULL;
p = &x;
int const ** const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);// Example 7
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const *pp = NULL;
pp = &p;
printf("%d\n", **pp);// Example 8
int const x = 10; // Definition must happen during declaration
int const * const p = &x; // Definition must happen during declaration
int const * const * const pp = &p; // Definition must happen during declaration
printf("%d\n", **pp);

N级取消引用

只要继续前进,但人类可能会驱逐您。

int x = 10;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
int ****pppp = &ppp;printf("%d \n", ****pppp);

#16楼

  • 如果const位于* 的左侧 ,则指向值(它是const int还是int const都没有关系)
  • 如果const* 的右边 ,则指向指针本身
  • 可以同时

重要的一点: const int *p 并不意味着您所指的值是常量! 。 这意味着您不能通过该指针更改它(意味着,您不能分配$ * p = ...`)。 该值本身可以以其他方式更改。 例如

int x = 5;
const int *p = &x;
x = 6; //legal
printf("%d", *p) // prints 6
*p = 7; //error

这主要用于函数签名中,以确保函数不会意外更改传递的参数。


#17楼

关于C ++中的const正确性,还有许多其他的细微之处。 我想这里的问题只是关于C的,但是由于标签是C ++,我将给出一些相关的示例:

  • 您通常将诸如字符串之类的大参数作为TYPE const &传递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重载来创建const和非const方法。 例如,如果定义T const& operator[] (unsigned i) 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 &引用,也可能会见证它所引用的值在其他地方已更改。

const int *,const int * const和int const *有什么区别?相关推荐

  1. const volatile同时限定一个类型int a = 10

    const和volatile放在一起的意义在于: (1)本程序段中不能对a作修改,任何修改都是非法的,或者至少是粗心,编译器应该报错,防止这种粗心: (2)另一个程序段则完全有可能修改,因此编译器最好 ...

  2. const int是什么类型_C++的const语义

    背景 我们都知道,const作为修饰符的时候,用来表明这个变量所代表的内存不可修改.因此,const修饰的变量必须在定义的时候就完成初始化,不然以后也没有机会了: const 但是请注意,这个不可修改 ...

  3. c语言const 修饰二级指针,C++中const修饰二级指针(从类型‘int**’到类型‘const int**’的转换无效)...

    先上代码: void func(const int ** arg) { } int main(int argc, char **argv) { int **p; func(p); return 0; ...

  4. 错误 LNK2019 无法解析的外部符号 “__declspec(dllimport) public: int __thiscall osg::Referenced::ref(void)const “

    前言 错误 LNK2019 无法解析的外部符号 "__declspec(dllimport) public: int __thiscall osg::Referenced::ref(void ...

  5. c语言 define和int,C语言中define与const的用法区别分析

    其实这个是困惑了我好久的问题,没想到在上机课做到的题里找到了答案--我的困惑是:#define与const到底有什么区别. 题目:  代码如下 复制代码 #define N 2 #define M N ...

  6. c语言const限制什么,[C语言]类型限定词const解析

    标签: 作为C90增加的一个受限类型关键字,const赋予了它修饰的变量一个新属性--不变性,如果一个变量声明中带有关键字const,则无法通过赋值.增减运算来修改该变量的值. 一.指针与const结 ...

  7. 类与对象:类的6个默认成员函数: 构造函数、析构函数、拷贝构造函数、赋值操作符重载、默认拷贝构造与赋值运算符重载的问题、const成员函数、 取地址及const取地址操作符重载

    1.类的6个默认成员函数 如果一个类中什么成员都没有,简称为空类.任何一个类在我们不写的情况下,都会自动生成下面6个默认成员函数. 构造函数 析构函数 拷贝构造函数 赋值操作符重载 const成员函数 ...

  8. c语言const字符串,C语言之正确使用const

    一.const用途 const是一个C语言的关键字,它限定一个变量不允许被改变. 1.const与基本类型 const char m;//限定m不可变. 2.const与指针 1).const在*前面 ...

  9. const对象只能调用const成员函数、不能调用非const成员函数;非const对象可以调用const成员函数

    引发原因: 由调用成员函数时隐式传入的当前对象的this指针引起. 1. 非const成员函数中的隐式参数:classA* this 2. const成员函数中的隐式参数:const classA* ...

  10. getch()与_getch()、不能将const char*类型的值分配到const* 类型的实体

    参考1:getch()与_getch() 添加预处理 项目 -> 属性 -> 配置属性 -> C/C++ -> 预处理器 -> 预处理器定义 -> 编辑中添加:_C ...

最新文章

  1. 深度学习前人精度很高了,该怎么创新?
  2. Vue之axios发送Ajax请求
  3. 笔记 | 那些不得不掌握的卷积神经网络CNN的架构
  4. Recurrent Neural Network[Quasi RNN]
  5. 直接插入排序,折半插入排序,希尔排序,简单选择排序,冒泡排序,快速排序模板以及比较次数与移动次数的分析,折半搜索算法模板
  6. 表妹好奇地问的飞鸽传书
  7. mysql 最短路经_poj 3613 Cow Relays 经L边的最短路 | 学步园
  8. phpcmsV9一、二级导航栏目loop循环输出、当前高亮显示
  9. 基于JAVA+SpringMVC+Mybatis+MYSQL的球鞋购物系统
  10. linux的三大服务器,Linux三大重要事件
  11. {工作记录}遇到过的网络攻击合集爬虫User-Agent记录..{持续更新}
  12. idea 导出项目到eclipse
  13. 深度学习之 梯度消失与爆炸原因公式推导
  14. 怎么自己建网站?自己建网站要注意以下4点
  15. 两轮电动车越来越拥挤了
  16. php识别word语言,PHP读取word文档
  17. 判断两个单词是否互为变位词
  18. 计算机基础知识(基础入门小白专属)三
  19. python-opencv基础
  20. Coremail2021邮件安全竞赛正式开幕!快来报名吧!

热门文章

  1. Android 抓取app进程 hprof 文件
  2. Promise入门详解和基本用法 我来教你
  3. 第十、十一周项目五 - 摩托车继承自行车和机动车
  4. Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性-[Android取经之路]
  5. ValueTransformer
  6. Swift URL含有中文的处理
  7. animated bar chart race下载_下载腾讯会议
  8. Selenium-switch_to_window出现删除线
  9. JavaWeb--MVC案例1-------(4)删除
  10. replace和replacAll