您的位置:首页 > 编程语言 > C语言/C++

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

2012-10-15 22:10 218 查看
一、对于基本声明

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: