zoukankan      html  css  js  c++  java
  • c++学习总结--复合类型,const。

    复习c++,有必要对一些东西做一下笔记,方便以后学习,如有问题,欢迎提出。

    首先,最常用两种复合类型应该是引用和指针。

    所谓复合类型,是在基本类型基础(如:int)上定义的类型。

    引用是c++的一个复合类型,首先,它和指针不同的是它并不是一个对象,仅仅只是另一个对象的别名。而且,引用绑定的东西必须是一个对象,引用不是对象,所以定义引用的引用是不合法的。

    也不能定义字面量的引用。同时,普通引用的绑定对象与引用定义类型必须相同。

    如:

    int &a=10;//错误的,不能定义字面量
    double b = 1.22;
    int &c = b;//错误,必须是同一种类型。

    虽然,普通的引用不能这么定义。

    关于const引用:

    但是const引用却可以,这意味着,像下面这样的代码是合理的:

    实际上,这种形式正式下面要讲的顶层const,约定指向对象时const,它是可以直接用常数为引用赋值,注意对比上面的。

    这也正是为什么可以为顶层const的函数参数传递常数的原因。

    const int &a=10;
    double b = 1.22;
    const int &c=b;
    const int &d = 2*b;

    为什么const可以呢?这样代码在编译过程中是这样的

    例如第三个:

    int tem = b;
    const int &c=tem;

    系统生成了临时对象。在c++primer中,作者给了这样一个解释,const的引用时不允许对const所修饰的对象进行改变,这意味着,无法改变const引用所绑定的对象,自然也

    无法改变tem,但是普通的引用,我们肯定是希望改变引用所绑定的对象的,不然为什么要用引用,既然如此,如果这个规则在普通引用也试用,那改变的将是临时对象,这肯定是矛盾的。

    指针是另外一种符合类型。

    指针是对象,这个和引用是不同的,它绑定的是另外一个对象的地址。对未知地址的操作可能造成意想不到的效果。所以在指针并不知道指向哪里是,可以先指向NULL,或者c++新标准的nullptr。NULL是预处理变量,不属于std空间,可以直接用。

    指针数组和数组指针:

    看这两种指针定义:int *p[3]和int (*p)[3],有什么不同呢。

    int *p[3],强调了p[3]保存的是int *,也就是这是一个保存指针的数组,内存是三个int单元。

    int (*p)[3],强调的是p是指针,它指向的是一个大小为三的int数组。这意味着p+1,是下一个大小为三的数组首地址,可以当成一个n行3列的二维数组来用。

    const是一个限定符,表示常量。

    指向常量的指针和指针常量:

    被const限定的指针和引用,相当于签订了协议,表示这个指针或引用所对应的值将不会改变,然而所对应的值是否是常量并不要求,就好像我只约束我自己,你那边怎么样我不管。

    这意味着普通的指针或者引用不能绑定常量地址,而指向的常量指针或引用这可以绑定普通地址。

    指向常量的指针:如:const int  *a;指约束指向的地址值应该是常量。

    还有一种是 常量指针:int *const a;指约束自己,指针本身是常量。

    顶层const和底层const:

    top-level const(顶层const):本身是const

    low-leve const(底层const):指向对象是const

    之所以这样分类是,因为,底层const约束自己不改变指向的值,所以在执行拷贝或拷出的时候,它要严格约定双方都是底层,不允许对方改变指向对象的值。

    而顶层const则约束的是自己,也就是指针或者别的基本数据类型本身不被改变,这意味着,在拷入和拷出并不需要都是顶层const,因为这样的操作不会改变他自己。

    关于顶层const的拷贝,举例子:

    int i = 0;
    const int c = 2;
    i = c;

    c是一个顶层const,因为它本身就是不可改变的对象,这种值拷贝并不在乎c是否为const。

    关于底层const的拷贝,也举个例子:

    const int *b = 2;
    int *p = b; //错误的

    这种情况下是错误的,底层const的拷出是严格的,b已经约定了它指向的对象是不会被改变的,而p变量本身没有这种约定,b是不放心的。也就是说底层const在拷出的时候是严格的,双方都应该是底层const。但是对于底层const,拷入确实可以的:

    int i = 0;
    const *p = &i;

    这是可以的,普通的int *可以转换成const int*。

    const形参和实参:

    实际上,顶层const作为形参是会被编译器忽略掉的,什么意思,我们看个例子:

    void fun(const int a);
    void fun(int a);

    看这两种函数声明,我们以为很开心的重载了,但是最后确报错了,实际上,忽略了顶层const,这两种声明是完全一样的。

    我们可以对比这一种情况,如果还分不清底层或者顶层const的话:

    void fun(const int& a);
    void fun(int &a);

    尽量使用常量引用:

    实际上,在前面已经提到过:

    int a = 1;
    int &b = a;
    //我们可以这么用
    /但不可以这么用
    int &c = 1;  //不可以
    //但可以这么用
    const int &d = 1;

    要是是这样一个函数:

    void fun(int &a);

    如果这么调用:

    fun(2);

    会报错。

    但是如果是这样的声明:

    void fun(const int &a);

    就不会报错了。

  • 相关阅读:
    Javascript注销Window认证登录信息
    Asp.Net文件下载
    Python Beginner's Guide
    StructureMap
    Telerik RadGanttView示例
    SharePoint Server 2010 备份还原和部署
    Bootstrap
    Javascript面向对象基础
    .NET Regular Expressions
    Javascript Arguments Callee Caller
  • 原文地址:https://www.cnblogs.com/wuweixin/p/5232803.html
Copyright © 2011-2022 走看看