Thinking in C++【7】常量Const

1.值替代

  • 预处理器的工作:预处理器只做文本替代,无类型检查概念,也无类型检查功能。预处理器在C中用值替代的典型用法是宏定义:
    #define BUFSIZE 100
    
    缺点:变量无类型信息,会隐藏一些很难发现的错误。
  • 编译器的工作:使用const
    const int bufsize = 100;
    

2.头文件里的const

  • 无论是使用**#define还是const**,都要把它们放在头文件里。通过包含头文件,可以把const定义单独放在一个地方并把它分配一个编译单元
  • const默认为内部连接,即仅在const被定义过的文件里才是可见的,而在连接时不被其他编译单元看到。
  • C++并不为const创建存储空间,而是把它保存在符号表里。但若使用extern const声明常量,可以强制进行存储空间分配,以使得外部连接可以正常进行。

3.编译器不知道存储空间的内容

  • 不能在编译期间使用const聚合的内存空间的值。因为编译器在编译期间不需要知道存储的内容。
  • 以下的非法使用:
    const int i[] = {
          
          1,2,3,4};
    float f[i[3]];   //Illgal
    

3.const:C与C++的区别

  • 在C++中,编译器在进行类型检查之后,也许会把值折叠到代码中,因此,C++默认不给const分配地址空间。

4.const指针

  • 指向const的指针:
    定义指针的技巧是,在标识符的开始处读它,并从里像外读,“u是一个指针,它指向const int”。由于u不是const,故此处不需要初始化。
    const int* u;
    
  • const指针
    读成**“w是个指针,这个指针是指向int的const指针”**。由于它是const指针,因此编译器要求给它一个初始值。
    int d = 1;
    int* const w = &d;
    

5.指针格式

指针‘*’是 与标识符结合,而不是与数据类型结合,因此它可以放在类型名和标识符之间的任何地方。

int *u = &i, v = 0;

6.传递和返回地址


//:C08:ConstPointer.cpp
void t(int*);   //t()的参数是非const指针
void u(const int* cip) {
    
        //u()的参数是const指针
    //! *cip = 2;   //const指针的内容不可修改
    int i = *cip;
    //! int * ip2 = cip;    //const指针的z地址也不可复制给非const指针
}
//编译器建立了const char*,并把它存储在静态存储区中
const char* v(){
    
    
    return "result of function v()";
}
//w()的返回值要求这个指针及这个指针所指向的对象均为常量。
const int* const w(){
    
    
    static int i;
    return &i;
}

int main() {
    
    
    int x = 0;
    int* ip = &x;
    const int* cip = &x;
    t(ip);
    //! t(cip);     //不可将const指针传递给非const参数
    u(ip);      //可以将非const指针传递给const参数
    u(cip);
    //! char* cp = v();         //不可将const指针传递给非const参数
    const char* cpp = v();
    //! int * ip2 = w();        //不可将const指针传递给非const参数
    const int* const ccip = w();
    const int* cip2 = w();
    
    
}

7.函数后面加const修饰:int f() const {}

  • 给隐含的this指针加const,表示这个this指向的东西是const的,也就是说这个函数中无法改动数据成员了。const是一种保证,告诉你这个成员不会改变对象的状态。
    声明一个成员函数的时候用const关键字是用来说明这个函数是 “只读(read-only)”函数,也就是说明这个函数不会修改任何数据成员(object)。 为了声明一个const成员函数, 把const关键字放在函数括号的后面。声明和定义的时候都应该放const关键字。
    任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提高程序的健壮性
class temp
{
    
    
public:
    temp(int age);
    int getAge() const;
    void setNum(int num);
private:
    int age;
};

temp::temp(int age)
{
    
    
    this->age = age;
}

int temp::getAge() const
{
    
    
    age+=10; // #Error...error C2166: l-value specifies const object #
    return age;
}

猜你喜欢

转载自blog.csdn.net/qq_43118572/article/details/112346069