C/C++语言中关于const用法的总结(2)

#define I = 10
const long &i = 10;
// 由于编译器的优化,使得在const long i=10时i不被分配内存
// 而是已10直接代入以后的引用中,以致在以后的代码中没有错误
//一旦你关闭所有优化措施,即使const long i = 10也会引起后面的编译错误。
char h = I; // 正确
char h = i; // 编译警告,可能由于数的截短带来错误赋值2.使用const可以避免不必要的内存分配

从汇编的角度来看,const定义常量只是给出了对应的内存地址, 而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。例子如下:

#define k "Hello world!"
const char pk[]="Hello world!";
printf(k);      // 为k分配了第一次内存
printf(pk);    // 为pk一次分配了内存,以后不再分配
printf(k);      // 为k分配了第二次内存
printf(pk);三. 使用const的一些注意事项

1.修改const 所修饰的常量值

以下例子中,i为const修饰的变量,可以通过对i进行类型强制转换,将地址赋给一个新的变量,对该新的变量再作修改即可以改变原来const 修饰的常值。

const int i=0;
int *p=(int*)&i;
p=100;2.构造函数不能被声明为const

3.const数据成员的初始化只能在类的构造函数的初始化表中进行

class A
{
public:
    const int a;
    A(int x):a(x)//正确
    {
        a = x;//错误
    }
};1
4.在参数中使用const应该使用引用或指针,而不是一般的对象实例

合理利用const在成员函数中的三种用法(参数、返回值、函数),一般来说,不要轻易的将函数的返回值类型定为const;另外,除了重载操作符外一般不要将返回值类型定为对某个对象的const引用。

5.对于使用const修饰来指针的情况

对于以下情况,const放在变量声明符的前后位置效果是一样的,这种情况下不允许对指针a 的内容进行更改操作:

int i;
const int *a = &i;
int const*a = &i;1
但是,如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即该指针指向一个地址,该地址的内容不可变;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量:

int i;
// 以下一行表示a是一个指针,可以任意指向int常量或者int变量
// 它总是把它所指向的目标当作一个int常量
// 也可以写成int const* a
const int *a = &i;
// 以下一行表示a是一个指针常量,
// 初始化的时候必须固定指向一个int变量
// 之后就不能再指向别的地方了
// 但是指针指向的内容可以改变
int *const a = &i;6.指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如以下例子中a++是错误的:

int *const a = &i;
a++;  // 错误,a指针本身是常量,不能再指向别的地方7.当指针本身和指针所指向的内容均为常量时

这种情况下可写为:

const int * const a = &i;8.const成员函数返回的引用,也是const

#include<iostream>
using namespace std;
class A
{
public:
    int x;
    void set(int x){this->x = x;}
    // const成员函数返回的引用也是const,a
    // 如果把A&前面的const去掉会出错
    // 因为返回的是一个const的对象,返回类型却不是const
    // 返回的内容和返回的类型不符
    const A& Test1()const
    {
    // 错误。这是const成员函数的特点
    x = 2;
    // 不限于*this。不管返回的是什么,哪怕是一个定义为非const的对象,结果也是一样的
    return *this;
    }
};

int main()
{
    A a, b;
    // 正确,虽然返回的是一个const,却用另一个非const来接收
    b = a.Test1();
    // 错误,既然是别名,那么别名的类型要与原来的类型相同
    A &c = a.Test1();
    // 正确虽然在a.Test1()中a不能改变,但是这里已经出了这个成员函数的作用域
    a.set(2);
    // 正确,b接收了a.Test1()返回的数据的内容,但是它不是const
    b.set(2);
    // 错误。a.Test1()是一个对象,这个对象是它的返回值
    // 虽然没有名字,但是它就是a.Test1()的返回值
    // 值是a.Test1()返回的值,类型是a.Test1()返回的类型
    a.Test1().set(2);
    return 0;
}9.mutable将数据声明为可变数据成员

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/4eef6ea6f221513d0e9aa91f004e05d8.html