c++中const关键字使用

一、c和c++区别

c语言const的特点:

1.c语言中const变量是只读的,本质还是变量
2.const修饰的变量在棧上分配空间
3.const修饰的全局变量在只读存储区分配空间
4.const只在编译期有用,运行期无用

总结:const修饰的变量不是真的常量,只是告诉编译器该变量不能出现在赋值符号的左边

c++中const在c的基础上进行了升级

1.当碰到const声明时,将常量纳入符号表
2.编译期如果发现使用常量,直接用符号表中的值进行替换
3.编译器若发现一下情况则给对应的常量分配存储空间
    ·对const使用extern
    ·对const使用&操作符

c++中const与宏的区别

1.const常量由编译器处理
2.编译器对const常量进行类型检查和作用域检查
3.宏由预处理处理,只是单纯的文本替换

关于c++中const&分配存储空间的代码

void test_const(){
    const int a = 3;
    int *p = (int *)&a;
    *p = 5;
    cout << "a = " << a << endl;
    cout << "*p = " << *p << endl;
    cout << "&a = " << &a << endl;
    cout << "p = " << p << endl;
}
输出:
a = 3
*p = 5
&a = 0x7ffeec3a8a3c
p = 0x7ffeec3a8a3c

发现a的值为3,但是*p的值是5,验证了之前说的符号表中的值进行替换,而第二行用到了&a对a又分配了空间,*p则是改变了分配的空间的值

二、const修饰符的使用

1.const与指针的搭配

int a = 2, b = 3;

int * const p1 = &a;
const int *  p2 = &a;

*p1 = 3; // 正常赋值
p1 = &b; // 报错,指针指向不能改变

*p2 = 3; // 报错,指针指向的值不能改变
p2 = &b; // 正常修改指针指向

2.const成员函数

·const对象调用
·不允许修改任何non-static成员变量
·常量性不同,可以进行重载

下面引用effective C++里面的例子

class TextBlock{
public:
    TextBlock(string text):text(text){

    }
    const char& operator[](std::size_t pos) const{  // operator[] for const对象
        return text[pos];
    }

    char& operator[](std::size_t pos) {  // operator[] for non-const对象
        return text[pos];
    }
    
    void setText(std::string text) const{
        this->text = text;
    }

private:
    std::string text;
};

int main(){
    TextBlock tb("hello");
    const TextBlock tcb("world");
    std::cout << tb[0];
    std::cout << tcb[0];

    tb[0]='x'; // 正常赋值
    tcb[0]='x'; // 编译错误,返回的是const
    
    tb.setText("abc"); // 编译错误,no viable overloaded '=' 将const去掉正常赋值
    return 0;
}

1.const对象调用的是const声明的成员函数,

2.这里面两个函数都返回都是char&,如果返回都是char,那么也同样无法通过编译(原因是如果函数返回值是内置类型,那么改动返回值不合法,即使合法,也是一个副本,也不是你想要的结果)

3.setText方法设置成const则该成员函数不能修改任何non-static成员变量

有些时候,必须使用const成员避免一些莫名其妙的问题如:(a*b) = c;

class Complex{
public:
    Complex(int real, int imag):real(real),imag(imag){

    }
    const Complex operator*(const Complex& comp1){
        Complex c(0,0);
        c.real = this->real * comp1.real - this->imag*comp1.imag;
        c.imag = this->real * comp1.imag + this->imag * comp1.real;
        return c;
    }
    void show(){
        cout << this->real << " + " << this->imag << "i" << endl;
    }
private:
    int real;
    int imag;
};


int main(){
    Complex c1(2,3);
    Complex c2(3,2);
    Complex c3 = c1*c2;
    c3.show();

    Complex c4(1,1);
    (c1*c2) = c4;
    return 0;
}

(c1*c2) = c4这种代码不应该出现,但是编译器如果重载操作符opertor*不返回一个const的话,那么这种不合理现象只能在运行期发现,加上const则在编译器就能发现

3.const修饰函数参数

当函数参数为const的引用的时候,会创建临时变量:
·实参类型正确,但是不是左值
·实参类型不正确,但是可以转换成正确的类型

借用c++ primer plus例子

    double refcube(const double &ra){
        return ra*ra*ra;
    }
    
    double side = 3.0;
    double * pd = &side;
    double & rd = side;
    long edge = 5l;
    double lens[4] = {2.0,5.0,10.0,2.2};
    
    double c1 = refcube(side);  // 类型正确,左值
    double c2 = refcube(lens[2]); // 类型正确,左值
    double c3 = refcube(rd); // 类型正确,左值
    double c4 = refcube(*pd); // 类型正确,左值
    double c5 = refcube(edge); // 类型不正确,ra是一个临时变量
    double c6 = refcube(7.0); // 类型正确,不是左值,ra是一个临时变量
    double c7 = refcube(side+7.0); // 类型正确,不是左值,ra是一个临时变量

解释下,左值是可以被引用的值,例如:变量,数组,结构成员,引用,解除引用的指针都是左值,非左值包括字面量,和包含多项的表达式

正常情况下,接受引用参数的函数的意图是修改作为参数传递的变量,如果创建临时变量,则在函数体内修改,并不能改变原来的变量,显然这不是开发者的意图,c++在没有const的情况下就是这么做的,去掉const发现编译器报错。但是现在refcube函数传递的变量只是使用值,所以临时变量并不影响

引用参数声明为const理由有三个:

·避免无意中修改数据的编程错误
·使用const能处理const和non-const参数,否则只能接受non-const参数
·是函数能正确生成并使用临时变量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值