草庐IT

C++ 中常量引用、指向常量的指针、常量指针的区别

runoob 2023-03-28 原文

先初步了解引用、指针的一些注意事项。

  • 引用并非对象
  • 引用必须初始化
  • 引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起
  • 类型要严格匹配
int &a = 10;             //错误:引用类型的初始值必须是一个对象  
  
double a = 3.14;  
int &b = a;              //错误:此处引用类型的初始值必须是int型对象

指针本身就是对象

指针的类型要和它指向的对象严格匹配

double dval;  
double *pd = &dval;      //正确  
double *pd2 = pd;        //正确  
  
int *pi = pd;            //错误:指针pi的类型和pd的类型不匹配  
pi = &dval;              //错误:试图把double型对象的地址赋给int型指针  

有例外:引入const 限定符

常量引用

初始化常量引用时允许用任意表达式作为初始值

int i = 42;  
const int &r1 = i;       //正确:允许将const int & 绑定到一个普通int对象上  
const int &r2 = 42;      //正确  
const int &r3 = r1 * 2;  //正确  
int &r4 = r1 * 2;        //错误  
  
double dval = 3.14;  
const int &ri = dval;    //正确  
//等价于  
const int temp = dval;  
const int &ri = temp;  
  
int i = 42;  
int &r1 = i;  
const int &r2 = i;  
r1 = 0;                  //正确  
r2 = 0;                  //错误  

常量指针

定义: 又叫常指针,可以理解为常量的指针,也即这个是指针,但指向的是个常量,这个常量是指针的值(地址),而不是地址指向的值。

关键点:

  • 1.常量指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改;
  • 2.常量指针可以被赋值为变量的地址,之所以叫常量指针,是限制了通过这个指针修改变量的值;
  • 3.指针还可以指向别处,因为指针本身只是个变量,可以指向任意地址;
 

代码形式:

int const* p;  const int* p;

指针常量

定义:本质是一个常量,而用指针修饰它。指针常量的值是指针,这个值因为是常量,所以不能被赋值。

关键点:

  • 1.它是个常量!
  • 2.指针所保存的地址可以改变,然而指针所指向的值却不可以改变;
  • 3.指针本身是常量,指向的地址不可以变化,但是指向的地址所对应的内容可以变化;
  •  

    代码形式:

    int* const p;

    指向常量的常指针

    定义:指向常量的指针常量就是一个常量,且它指向的对象也是一个常量。

    关键点:

    • 1.一个指针常量,指向的是一个指针对象;
    • 2.它指向的指针对象且是一个常量,即它指向的对象不能变化;

    代码形式:

    const int* const p;

    那如何区分这几类呢? 带两个const的肯定是指向常量的常指针,很容易理解,主要是如何区分常量指针和指针常量:

    一种方式是看 * 和 const 的排列顺序,比如

    int const* p;    //const * 即常量指针
    const int* p;    //const * 即常量指针
    int* const p;    //* const 即指针常量

    还一种方式是看const离谁近,即从右往左看,比如

    int const* p;    //const修饰的是*p,即*p的内容不可通过p改变,但p不是const,p可以修改,*p不可修改;
    const int* p;    //同上
    int* const p;    //const修饰的是p,p是指针,p指向的地址不能修改,p不能修改,但*p可以修改;

    实例

    //-------常量指针-------
    const int *p1 = &a;
    a = 300;     //OK,仍然可以通过原来的声明修改值,
    //*p1 = 56;  //Error,*p1是const int的,不可修改,即常量指针不可修改其指向地址
    p1 = &b;     //OK,指针还可以指向别处,因为指针只是个变量,可以随意指向;
    
    //-------指针常量-------//
    int*  const p2 = &a;
    a = 500;     //OK,仍然可以通过原来的声明修改值,
    *p2 = 400;   //OK,指针是常量,指向的地址不可以变化,但是指向的地址所对应的内容可以变化
    //p2 = &b;     //Error,因为p2是const 指针,因此不能改变p2指向的内容
    
    //-------指向常量的常量指针-------//
    const int* const p3 = &a;
    //*p3 = 1;    //Error
    //p3 = &b;    //Error
    a = 5000;    //OK,仍然可以通过原来的声明修改值

    在实际应用中,常量指针要比指针常量用的多,比如常量指针经常用在函数传参中,以避免函数内部修改内容。

    size_t strlen(const char* src); //常量指针,src的值不可改变;
    char a[] = "hello";
    char b[] = "world";
    size_t a1 = strlen(a);
    size_t b1 = strlen(b);

    虽然a、b是可以修改的,但是可以保证在strlen函数内部不会修改a、b的内容。

    空指针、野指针

    既然讲到了指针,那顺便说一下空指针、野指针的问题。

    空指针就是保存地址为空的指针,使用指针时必须先判断是否空指针,很多问题都是这一步导致的。

    野指针是在delete掉指针之后,没有置0,导致指针随意指向了一个内存地址,如果继续使用,会造成不可预知的内存错误。

    另外指针的误用很容易造成BUG或者内存泄漏。

    看代码:

    //-------空指针-------//
    int *p4 = NULL;
    //printf("%d",*p4); //运行Error,使用指针时必须先判断是否空指针
    
    //-------野指针(悬浮、迷途指针)-------//
    int *p5 = new int(5);
    delete p5;
    p5 = NULL; //一定要有这一步
    printf("%d",*p5);  //隐藏bug,delete掉指针后一定要置0,不然指针指向位置不可控,运行中可导致系统挂掉
    
    //-------指针的内存泄漏-------//
    int *p6 = new int(6);
    p6 = new int(7); //p6原本指向的那块内存尚未释放,结果p6又指向了别处,原来new的内存无法访问,也无法delete了,造成memory leak

    参考地址:

    http://blog.csdn.net/Rueing839/article/details/48416907

    http://www.cnblogs.com/lizhenghn/p/3630405.html

有关C++ 中常量引用、指向常量的指针、常量指针的区别的更多相关文章

  1. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

    在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

  2. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  3. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  4. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  5. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  6. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  7. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  8. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  9. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  10. ruby - 一个 YAML 对象可以引用另一个吗? - 2

    我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的ruby​​yaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir

随机推荐