C++关键字 之 const使用详解

一、对于基本声明
const int X = 100;
const加在int X的前面,用来定义一个不可被改变的整型常量X,这个X必须在声明时赋值。这种用法用来替代传统的

#define

#define PI 3.14
改为

const float PI = 3.14;

总结:C++代码中应该使用const替换#define,const常量必须在声明时初始化

二、对于指针


如下几种指针
int x = 100;
int* p = &x;                      // 1. 非const指针,非const数据
const int* p = &x;            // 2. 非const指针,const数据
int const *p = &x;            // 3. 非const指针,const数据
int* const p = &x;            // 4. const指针,非const数据
const int* const p = &x;  // 5. const指针,const数据

可以看出2和3的功能是完全一样的,只是两种不同的写法,这种指针表示指针本身可以修改,但是指向的数据不能通过

这个指针修改。即p可以指向其他的变量,但是不能通过*p修改x的值。
对于4,允许通过指针修改数据,但是不能修改指针本身。即p只能指向x,可以通过*p修改x的值。
5的功能是前两种的叠加,即指针不能修改,数据也不能修改

总结:对于指针来说,如果const在*的左边,说明数据是const的,如果const在*的右面,说明指针是const的,如果是

指针是const的话,必须在声明时为指针初始化。

三、对于函数的参数


以下几种形式
void method(const int x);        // 1. 普通变量的const
void method(const int& x);       // 2. 普通变量引用的const
void method(const int* p);       // 3. 普通变量指针的const
void method(const MyClass x);    // 4. 类的const
void method(const MyClass& x);   // 5. 类引用的const
void method(const MyClass* x);   // 6. 类指针的const

对于1和2来说,这两种形式完全没有意义,这里就不多说了。
对于3来说,如果传递数组的首地址是有意义的,否则同1和2一样,也无意义例如
int a[10] = {……};
method(a);
那么a中所有的元素都不能被修改。通常为char*类型的参数加上const修饰,保证字符串不会在函数内被修改,即void

method(const char* str);
第4种用法也不应该出现,因为默认情况下C++的函数参数都是值传递。例:
MyClass c;
method(c);  // 声明void method(const MyClass x);
这是C++会为c产生一个临时变量,也就是说传递到method中的是c的副本,这样增大了系统开销。所以传递类时一般要使

用5和6的方法。
对比5和6,没有本质区别,只是由于指针和引用的不同,指针可能为空值,函数进入时要检查参数的合法性。所以通常

使用第5种方法。

总结:对于一般内置类型来说(int, char等)不管引用还是指针,都没有必要传递加const修饰的参数,数组首地址除外

。对于类应该传递const引用,这样能提高运行时效率。(但是对于STL迭代器等少部分类除外,参考Effective C++

Item 20)

四,对于函数返回值


函数返回值加const修饰,对于内置类型来说(int, char等)指的是函数的返回值的初值不能被修改,同函数的参数一样

,函数的返回值也是值传递,所以对于内置类型来说,返回值前面加const基本上没有意义。
即,下面两种const返回值是不必要的
const int method(void);
const int& method(void);

下面要特别说明一下返回指针时加const修饰的情况
const int* method();
请参考下面两种实现方式
const int* method()    // 1
{
    int x = 100;
    return &x;        // 函数结束后x已经离开作用域,返回的是野指针
}

const int* method()   // 2
{
    int* x = new int(100);
    return x;         // 要记得在调用method后delete
}

对于返回对象时加const修饰的情况,和内置类型的情况基本相同,值传递时没有必要加const修饰,更不可返回类对象

的引用(类的operator =除外,下面章节会介绍)(参考Effective C++ Item10 & Item21),如果返回一个局部变量的

地址,或在堆上创建对象的地址时要小心,对于类的成员函数,需要返回内部数据时,应该返回const的指针,如下
class MyClass
{
    char* m_str;
    const char* GetString()
    {
        return m_str;    // 返回const,防止外部修改对象内部数据
    }
}

总结:返回值前面加const基本上没有意义,非类的成员函数返回const指针时要小心野指针和内存泄露的问题,不要返

回类对象的引用(类的operator =除外)

五、对于成员变量


class MyClass
{
    const int x = 100;
}

这种用法会造成空间的浪费,每个MyClass对象都要用4字节保存一个永远不变的常量。如果为某个类定义一个常量,应

该使用static const,如下
class MyClass
{
    static const int x = 100;
}

还有一种用法,可以在运行时对const成员变量初始化,使每个对象的const成员变量拥有不同的数值,如下:
class MyClass
{
public:
  MyClass ( int sz ) : size( sz ) {};
  const int size;
};

这个const成员变量只能在成员初始化列表中初始化。

总结:要使同一类型不同的对象拥有相同数值的const成员变量,使用static const,要使同一类型的不同对象拥有不同

数值的const成员变量,直接使用const,但是这个const成员变量应在成员初始化列表中初始化。

六、对于成员函数


函数的参数和返回值已经介绍过了,这里介绍const成员函数,如下 :
class MyClass
{
    void method() const
    {
    }
}

这个const写在成员函数的后面,区别于对返回值的修饰。在const成员函数中,不能修改任何一个非静态成员变量,也

不能调用其他非const成员函数修改成员变量。如下
class MyClass
{
    int a;
    static int s_a;
    void method() const
    {
        other_method();     // 错误
        a = 100;                 // 错误
        s_a = 100;             // OK
    }
    void other_method()
    {
        a = 100;    // OK
    }
}
另外要注意的是如果是const的对象,这个对象只能调用const成员函数,否则编译会出错,如下
void F(const MyClass& myclass)
{
    myclass. method();                 // OK
    myclass. other_method ();     // 错误,因为对象是const的,但是other_method可能会
                                                  // 改变对象的成员变量
}

还有一个例外,用C++关键字mutable标识的成员变量可以在const成员函数中修改。如下:
class MyClass
{
    mutable int a;
    void method() const
    {
        a = 100;            // OK
    }
}

总结:const写在成员函数后面可以定义const成员函数,const成员函数不能修改任何非静态成员变量(静态变量可以修

改),用mutable标识的成员变量例外,可以在const成员函数中修改,const的对象只能调用const成员函数。

七、对于类的operator =


类的operator应该返回const的引用,如下:
class MyClass
{
public:
    const MyClass& operator = (const MyClass& rhs)
    {
        ……
        return *this;
    }
}

参考Effective C++ Item 10。

八、默认的const


下面这种情况,声明char* 同时初始化字符串常量是,运行时会初始化char*为const:
char* str = "Hello";
str[0] = 'a';    // 运行时错误

因为编译时不会出错,只有运行时才报错,所以这里使用时要注意。

 

FROM:http://blog.csdn.net/macomfan/article/details/5884121

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值