const的基本使用
const的用法我觉得对于一个以后想着做一个优秀的程序员来说,这是必须熟练掌握的技能。因为网上有好多的文章介绍它的写的非常好,有的我就直接拿过来了~,现在我们来看看他的用法。
const 要求他所修饰的对象为常量,不可被改变,不可被赋值,不可作为左值.
1、函数体内修饰局部变量
例:
1
2
3
|
void func(){
const int a=0;
}
|
const作为一个类型限定词,和int有相同的地位。
const int a; int const a;
是等价的。于是此处我们一定要清晰的明白,const修饰的对象是谁,是a还是int
const要求他所修饰的对象为常量,不可被改变,不可被赋值,不可作为左值(l-value)。所以很明显它修饰的是a。这是一个很常见的使用方式:
const double pi=3.14;
在程序的后面如果企图对pi再次赋值或者修改就会出错。然后看一个稍微复杂的例子。
const int* p;
因为int* p;和 int *p;是等价的。
所以const int (*p)和int const (*p)是等价的。现在一目了然const 修饰的是谁? 是*p.所以p+=1;是合法的
*p+=1;是非法的因为const修饰了你。
int* const p;那这个什么意思?
看const修饰的是什么? 它修饰的p。但是p是一个int型的指针,所以这个指针的地址没有办法修改。
p+=1; //这就是非法的
*p+=1; //这个是合法的
再看一个更复杂的例子,它是上面二者的综合
const int* const p;说明p自己是常量,且p指向的变量也是常量。
于是
p+=1; //非法
*p+=1; //非法
const 还有一个作用就是用于修饰常量静态字符串。例如:
const char* name=David;
如果没有const,我们可能会在后面有意无意的写name[4]='x'这样的语句,这样会导致对只读内存区域的赋值,然后程序会立刻异常终止。有了 const,这个错误就能在程序被编译的时候就立即检查出来,这就是const的好处。让逻辑错误在编译期被发现。
2、在函数声明时修饰参数
举个例子void * myMemMove(void *dst,constvoid *src,intcount )这是我写的memmove函数的声明,这个函数的意思就是(任意类型)把*src的内容复制给*dst,我们现在很明显的看到*src它只让你复制,你不能修改它的值,所以怕你在以后的函数的定义里出现问题现在在声明里限制你。
3、全局变量
我们的原则依然是,尽可能少的使用全局变量。我们的第二条规则 则是,尽可能多的使用const。如果一个全局变量只在本文件中使用,那么用法和前面所说的函数局部变量没有什么区别。如果它要在多个文件间共享,那么就牵扯到一个存储类型的问题。
有两种方式。
1.使用extern
例如
/* test.h */
extern const double pi;
/* test.c */
const double pi=3.14;
然后其他需要使用pi这个变量的,包含test.h
#include test.h
或者,自己把那句声明复制一遍就好。
这样做的结果是,整个程序链接完后,所有需要使用pi这个变量的共享一个存储区域。
2.使用static,静态外部存储类
/* constant.h */
static const pi=3.14;
需要使用这个变量的*.c文件中,必须包含这个头文件。
前面的static一定不能少。否则链接的时候会报告说该变量被多次定义。这样做的结果是,每个包含了constant.h的*.c文件,都有一份该变量自己的copy,该变量实际上还是被定义了多次,占用了多个存储空间,不过在加了static关键字后,解决了文件间重定义的冲突。坏处是浪费了存储空间,导致链接完后的可执行文件变大。但是通常,这个,小小几字节的变化,不是问题。好处是,你不用关心这个变量是在哪个文件中被初始化的。
其实const我觉得更多是程序员自己限制自己,自己告诉自己后面哪里不能出现错误
举个例子吧。
1
2
3
4
5
6
7
8
9
10
11
12
|
#include<stdio.h>
#include<Windows.h>
int main()
{
int *p;
const int a = 0;
p = &a;
*p = 3;
printf ( "a= %d \n" , a);
system ( "pause" );
return 0;
}
|
现在看看运行结果
现在我要说一个const操作里面比较骚的一些做法,
举个例子我们以前写过的一个类,我们会使用operator[]来返回一个reference的指向,这个一般情况我们都会写一个
const的也会写一个非const的opeartor[].这是我们最常见的一个代码:
1
2
3
4
5
6
7
8
|
T& operator[]( int position)
{
return xxx[position];
}
const T& operator[]( int position) const
{
return xxx[position];
}
|
这是我们平时写的初级的代码,但是现在当我们要写一个TextBlock内的opeartor[]不单只返回一个referencr了,也可能执行边界检查,日志访问信息,还有什么数据完善性检验等等一大堆繁琐的代码,这个时候当你实现operator[] const和operator[]() const,的时候两份代码大部分都一样,这里伴随的是代码重复,编译时间变长,维护代码膨胀等等头疼的问题. 当然啦,你可以让上述那些繁琐的函数全部封装的别的函数中,然后分别在operator[]()和operator[]()const当中调用但是你还说重复了一些代码比如两次return语句,函数调用.真正该做的是实现operator[]的机能一次并使用它两次。也就是你只需要写一个函数,令另外一个调用这个,这促使我们将常量性转移. 接下来 见证奇迹我们来看看下面这个代码是怎么实现的上述的操作的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class TextBlock
{
public :
...
const char & operator[](std:: size_t position) const
{
...
...
...
return text[position];
}
char & operator[](std:: size_t position)
{
return const_cast < char &>( static_cast < const TextBlock&>(* this )[position]);
}
};
|
来仔细看这个操作;return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
首先把*this强制转换为const TextBlock,再然后调用const的operator[],最后再把const的operator[]的返回值的const常量性取消,然后返回一个非const的值. 这里的调用实在是太妙了,我们可以思考一下,好好想想这里的深意.
但是会有人说,为什么不用const operator[]调用operator[]呢,这样强制两个都可以行的通啊.这样想是错的!
令const版本调用调用no-const版本以避免重复并不是你该做的事情. 记住const所修饰函数的承诺就是我绝对不会修改你,no-const函数可没有这种承诺,所以你让一个const函数去调用一个no-const函数是不现实的. over其实const有很多可以玩的属性,只要我们想到就可以去实现,这里就说这么一个就ok. 接下来我们来瞧瞧另外两个关键字.
C++中的const的使用详解
const在c/c++中还是会经常出现的,并且如果不理解const会在编程出现的错误而不知所措,无法理解。下面从几个角度简要理解const的内容,应该还是蛮有用的。
const与指针类型
const int*p = NULL; 和int const*p = NULL;是等价的。因为const都在“ * ”的前面,其实是以*为标志的。
1
2
3
4
|
1. int x = 3; const int *p = &x;
// p = &y;正确 , //*p = 4;错误
|
指针其实一般是4个字节长度。p的内容是存储0x….,就是其他数据的地址。因此这里的const修饰*p就是说:*p的内容是不可直接被赋值改变的。
而p本身存储的地址是可变的,可以变成其他的0x…..当p指向其他的数据地址时,*p也就随之变成新的数据。
1
|
int x = 3; int * const p = &x; //p = &y是错误的
|
总结:其实是看这个const是在的前面还是后面,如果在的前面,则表示修饰的是整个“ p ”,而在后面,则表示修饰的是只有p。
显然有:在前面,则表示整个*p是const的,因此p可以指向其他的地址,而*p则是const的,无法改变。同理,int *const p = &x;则表示指针p是固定的,就是说p指针存储的地址是固定的,其内容是const,因此无法修改为其他值(即指向其他地址)。
const与引用
1
2
|
int x = 3; const int &y = x;
//x = 10;正确 //y = 20; 错误
|
引用前面有const,所以不能通过y来修改x的值。
本人的理解:const int &y就是相当于const int *y1 = &x;然后y = 20就相当于*y1 = 20;这显然时不允许的(就如前面所说的,*p时const,无法直接赋值给*p)。因为引用就相当于给x取了一个别名y,此时y不就是y1指针所指的内容吗?也就是说上面的例子:y = 20;就是相当于 *y1 = 20.
错误的const使用
其他:const int x = 3; int *y = &x; 不能通过编译。因为可能通过*p修改本应该是const的x;
int x = 3; const int *y = &x; 这是可以的,这里的x是可变的,通过由于*y是const的,因此*y就是只能是读取x的值,而不具有写入x的权利。
总结:可以说是只能把一个东西权限缩小,而不能使其原始的权限增大。
const在函数中的应用
主要是防止函数的误操作,对值进行更改
1
2
3
4
|
void fun( const int &a, const int &b)
{
//这里就不能对a或b进行更改,否则会编译出错
}
|
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
原文链接:http://blog.csdn.net/hungryof/article/details/45619905