const 指针与指向const的指针

  最近在复习C++,指针这块真的是重难点,好久了也没有去理会,今晚好好总结一下const指针,很久没有写过博客了,记录一下~html

const指针的定义:ios

  const指针是指针变量的值一经初始化,就不能够改变指向,初始化是必要的。其定义形式以下:
type *const 指针名称;

  声明指针时,能够在类型前或后使用关键字const,也可在两个位置都使用。例如,下面都是合法的声明,可是含义大不一样:函数

const int * pOne;    //指向整形常量 的指针,它指向的值不能修改post

int * const pTwo;    //指向整形的常量指针 ,它不能在指向别的变量,但指向(变量)的值能够修改。 ui

const int *const pThree;  //指向整形常量 的常量指针 。它既不能再指向别的常量,指向的值也不能修改。url

理解这些声明的技巧在于,查看关键字const右边来肯定什么被声明为常量 ,若是该关键字的右边是类型,则值是常量;若是关键字的右边是指针变量,则指针自己是常量。下面的代码有助于说明这一点:spa

const int *p1;  //the int pointed to is constant

int * const p2; // p2 is constant, it can't point to anything else

 

const指针和const成员函数指针

能够将关键字用于成员函数。例如:code

class Rectangle { pubilc: ..... void SetLength(int length){itslength = length;} int GetLength() const {return itslength;}  //成员函数声明为常量
 ..... private: int itslength; int itswidth; };

当成员函数被声明为const时,若是试图修改对象的数据,编译器将视为错误。htm

若是声明了一个指向const对象的指针,则经过该指针只能调用const方法(成员函数)。

示例声明三个不一样的Rectangle对象:

Rectangle* pRect = new Rectangle; const Rectangle * pConstRect = new Rectangle;     //指向const对象
 Rectangle* const pConstPtr = new Rectangle;

// pConstRect是指向const对象的指针,它只能使用声明为const的成员函数,如GetLength()。

 

const指针和指向const的指针

当使用带有const的指针时其实有两种意思。一种指的是你不能修改指针自己的内容,另外一种指的是你不能修改指针指向的内容。听起来有点混淆一会放个例子上来就明白了。

      先说指向const的指针,它的意思是指针指向的内容是不能被修改的。它有两种写法。

      const int* p; (推荐)

      int const* p;

      第一种能够理解为,p是一个指针,它指向的内容是const int 类型。p自己不用初始化它能够指向任何标示符,但它指向的内容是不能被改变的。

      第二种很容易被理解成是p是一个指向int的const指针(指针自己不能被修改),但这样理解是错误的,它也是表示的是指向const的指针(指针指向的内容是不能被修改的),它跟第一种表达的是一个意思。为了不混淆推荐你们用第一种。

      再说const指针,它的意思是指针自己的值是不能被修改的。它只有一种写法

      int* const p=一个地址; (由于指针自己的值是不能被修改的因此它必须被初始化)

      这种形式能够被理解为,p是一个指针,这个指针是指向int 的const指针。它指向的值是能够被改变的如*p=3;

      还有一种状况是这个指针自己和它指向的内容都是不能被改变的,请往下看。

      const int* const p=一个地址;

      int const* const p=一个地址;

      看了上面的内容是否是有点晕,不要紧,你不用去背它,用的多了就知道了,还有个技巧,经过上面的观察咱们不难总结出一点规律,是什么呢?这个规律就是: 指向const的指针(指针指向的内容不能被修改)const关健字老是出如今*的左边而const指针(指针自己不能被修改)const关健字老是出如今*的右边,那不用说两个const中间加个*确定是指针自己和它指向的内容都是不能被改变的。有了这个规则是否是就好记多了。
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 #include <iostream>

using namespace std; int main(int argc, char *argv[]) { int a=3; int b; /*定义指向const的指针(指针指向的内容不能被修改)*/ 
    const int* p1; int const* p2; /*定义const指针(因为指针自己的值不能改变因此必须得初始化)*/ 
    int* const p3=&a; /*指针自己和它指向的内容都是不能被改变的因此也得初始化*/
    const int* const p4=&a; int const* const p5=&b; p1=p2=&a; //正确
     *p1=*p2=8; //不正确(指针指向的内容不能被修改)
    
     *p3=5; //正确
     p3=p1; //不正确(指针自己的值不能改变) 
 p4=p5;//不正确 (指针自己和它指向的内容都是不能被改变) 
     *p4=*p5=4; //不正确(指针自己和它指向的内容都是不能被改变) 
     
    return 0; }

 

const用法小结:
const最经常使用的就是定义常量,除此以外,它还能够修饰函数的参数、返回值和函数的定义体。
1. const修饰函数的参数
若是参数做输出用,不论它是什么数据类型,也不论它采用“指针传递”仍是“引用传递”,都不能加const 修饰,不然该参数将失去输出功能。
const 只能修饰输入参数:
若是输入参数采用“指针传递”,那么加const 修饰能够防止意外地改动该指针,起到保护做用。
将“const &”修饰输入参数的用法总结以下:
(1)对于非内部数据类型的输入参数,应该将“值传递”的方式改成“const 引用传递”,目的是提升效率。例如将void Func(A a) 改成void Func(const A &a)。
(2)对于内部数据类型的输入参数,不要将“值传递”的方式改成“const 引用传递”。不然既达不到提升效率的目的,又下降了函数的可理解性。例如void Func(int x) 不该该改成void Func(const int &x)。


2. const 修饰函数的返回值
若是给以“指针传递”方式的函数返回值加const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。例如函数
const char * GetString(void);
以下语句将出现编译错误:
char *str = GetString();
正确的用法是
const char *str = GetString();

若是返回值不是内部数据类型,将函数A GetA(void) 改写为const A & GetA(void)的确能提升效率。但此时千万千万要当心,必定要搞清楚函数到底是想返回一个对象的“拷贝”仍是仅返回“别名”就能够了,不然程序会出错。
函数返回值采用“引用传递”的场合并很少,这种方式通常只出如今类的赋值函数中,目的是为了实现链式表达。
例如:

class A
{
A & operate = (const A &other); // 赋值函数
};
A a, b, c; // a, b, c 为A 的对象
a = b = c; // 正常的链式赋值
(a = b) = c; // 不正常的链式赋值,但合法

若是将赋值函数的返回值加const 修饰,那么该返回值的内容不容许被改动。上例中,语句 a = b = c 仍然正确,可是语句 (a = b) = c 则是非法的。


3. const修饰成员函数
关于Const函数的几点规则:
a. const对象只能访问const成员函数,而非const对象能够访问任意的成员函数,包括const成员函数.
b. const对象的成员是不可修改的,然而const对象经过指针维护的对象倒是能够修改的.
c. const成员函数不能够修改对象的数据,无论对象是否具备const性质.它在编译时,以是否修改为员数据为依据,进行检查.
d. 然而加上mutable修饰符的数据成员,对于任何状况下经过任何手段均可修改,天然此时的const成员函数是能够修改它的

 

  版权全部,转载请注明转载地址:http://www.cnblogs.com/lihuidashen/p/4378884.html