likes
comments
collection
share

C++中的static和const

作者站长头像
站长
· 阅读数 4

static

  • 不考虑类的情况

    • 当同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。
    • 默认初始化为0,包括未初始化的全局静态变量与局部静态变量,都存在全局未初始化区.bss区
    • 静态变量在函数内定义,始终存在,且只进行一次初始化,具有记忆性,其作用范围与局部变量相同,函数退出后仍然存在,但不能使用,在下次调用时仍维持上次的值;
    • 在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
  • 考虑类的情况

    • static成员变量:只与类关联,不与类的对象关联。定义时要分配空间,不能在类声明中初始化,必须在类定义体外部初始化,初始化时不需要标示为static;可以被非static成员函数任意访问。
    • static成员函数:不具有this指针,无法访问类对象的非static成员变量和非static成员函数;不能被声明为const、虚函数和volatile;可以被非static成员函数任意访问
    • static成员函数不能被virtual修饰,static成员不属于任何对象或实例,所以加上virtual没有任何实际意义;静态成员函数没有this指针,虚函数的实现是为每一个对象分配一个vptr指针,而vptr是通过this指针调用的,所以不能为virtual;虚函数的调用关系,this->vptr->ctable->virtual function

const

  • const修饰普通类型的变量

    • 阻止一个变量被改变,可以使用const关键字,const常量在定义时必须初始化,之后无法更改
  • const 修饰指针变量

    • const 修饰指针指向的内容,指针常量,内容为不可变量
    • const 修饰指针,则指针为不可变量,即常量指针
    • const 修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量
  • const参数传递和函数返回值

    • const 修饰函数参数

      • 值传递的 const 修饰传递,一般这种情况不需要 const 修饰,因为函数会自动产生临时变量复制实参值,这个时候无论加不加const对实参不会产生任何影响
      • const 参数为指针时,可以防止指针被意外篡改
      • const参数为引用,自定义类型的参数传递,需要临时对象复制参数,对于临时对象的构造,需要调用构造函数,比较浪费时间,因此我们采取 const 外加引用传递的方法。
    • const 修饰返回值

      • const 修饰自定义类型的作为返回值,此时返回的值不能作为左值使用,既不能被赋值,也不能被修改。
      • const 修饰返回的指针或者引用,是否返回一个指向 const 的指针,取决于我们想让用户干什么。
  • 类相关const

    • const修饰类的成员变量,表示成员常量,不能被修改,同时它只能在初始化列表中赋值。
    • const修饰类的成员函数,则表明其是一个常函数,不能修改类的成员变量
    • const对象只能调用const成员函数。

顶层const和底层const

顶层const: 指针本身是个常量,const在*的右边

底层const: 指针所指的对象是个常量,const在*的左边

区分作用:

  • 当执行对象的拷贝操作时,顶层const不受影响,因为执行拷贝操作并不会改变被拷贝对象的值,但拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换,非常量可以转换为常量,反之不行
  • 使用命名的强制类型转换函数const_cast时,只能改变运算对象的底层const
int i = 0;
int *const p1 = &i;     // 不能改变p1的值,顶层const
const int ci = 42;      // 不能改变ci的值,顶层const
const int *p2 = &ci;    // 允许改变p2的值,底层const
const int *const p3 = p2;   // 靠右的const是顶层const,靠左的是底层const
const int &r = ci;      // 用于声明引用的const都是底层const
i = ci;                 // 正确:拷贝ci的值,ci是一个顶层const
p2 = p3;                // 正确:p2和p3指向的对象类型相同,p3顶层const不影响
int *p = p3;            // 错误:p3包含底层const,而p没有
p2 = &i;                // 正确:int*能转换成const int*
int &r = ci;            // 错误:普通的int& 不能绑定到int常量上
const int &r2 = i;      // 正确:const int&可以绑定到普通变量int上