C++指向常对象的指针变量

Posted LC编程开发者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++指向常对象的指针变量相关的知识,希望对你有一定的参考价值。

指向常对象的指针变量

       为了使读者更容易理解指向常对象的指针变量的概念和使用,首先了解指向常变量的指针变量,然后,再进一步研究指向常对象的指针变量。有如下的一个测试例子:

#include <iostream>

using namespace std;

int main()

{

    char str[] = "56789";

    char* pstr = str;

 

    *pstr = 'A';

    cout << "str = " << pstr << endl;

    return 0;

}

       程序的运行结果如下:

g++ test.cpp -o exe

wkf@ubuntu:~/c++$ ./exe

str = A6789

       在该程序中,定义了一个字符串数组。然后,定义char类型的指针变量pstr,指针变量pstr指向字符串数组str,然后,通过pstr修改str[]数组的第一个元素值。

       那么,上面的操作是合法的,如果把pstr定义为const类型,会怎么样?

       定义指向常变量的指针变量的一般形式为:

const 类型名* 指针变量名;

       所以,修改上面的例子,把pstr定义为const类型,如下:

const char* pstr = str;

       修改后的代码如下:

#include <iostream>

using namespace std;

int main()

{

    char str[] = "56789";

    const char* pstr = str;

 

    *pstr = 'A';

    cout << "str = " << pstr << endl;

    return 0;

}

       编译异常,异常信息如下:

wkf@ubuntu:~/c++$ g++ test.cpp -o exe

test.cpp: In function ‘int main()’:

test.cpp:8: error: assignment of read-only location ‘* pstr’

       表示pstr是一个const类型的指针,指向的数据是const类型,不可以修改,所以,执行:

*pstr = 'A';

       是异常的操作。

       注意:const 的位置是在最左侧,它与类型名 char* 紧接,表示指针变量 ptr 指向的char 变量是常量,不能通过 ptr 指针来改变其值。

下面归纳总结:

(1) 如果一个变量已被声明为常变量,只能用指向常变量的指针变量指向它。而不能用一般的(指向非const型变量的)指针变量去指向它。例如:

const char c[] = "wkf";     //定义const 类型的char 数组

const char *p1;     //定义p1 为指向const 类型的char 变量的指针

p1 = c;         //合法,p1 指向常变量

char *p2 = c;   //非法,p2 是普通char类型指针,不能够指向常变量

(2) 指向常变量的指针变量除了可以指向常变量(如上面(1)中所述)外,还可以指向为被声明为const的变量,此时,不能通过此指针变量来改变该变量的值,例如:

char c1 = 'a'//普通char 类型的变量

const char *p;  //const 修改char,所以,p 指向的内容是常量,不可以修改

p = &c1;        //p 这个指向常量的指针,也可以指向普通变量

*p = 'b';       //错误。。。因为p 指向的内容是常量,不可以修改

c1 = 'b';       //合法,因为c1 是普通变量,可以修改,只是,不可以通过p 指向常量的指针来修改其值

       所以,我们可以知道:指向常变量的指针变量可以指向一个非const变量。这时可以通过指针变量访问该变量,但不能改变该变量的值。如果不是通过指针变量访问,则变量的值是可以改变的。

注意:定义了指向常变量的指针变量p并使它指向c1,并不意味着把c1也声明为常变量,而只是在“通过指针变量引用c1时”,c1具有常变量的特征,其值不能改变。在其他情况下,c1仍然是一个普通的变量,其值是可以改变的。

       如果希望在任何情况下都不能改变c1的值,则应该把它定义为const类型,如:

const char c1 = 'a'; //此时,定义c1变量是常变量

(3) 如果函数的形参是指向非const型变量的指针,实参只能用指向非const变量的指针,而不能用指向const变量的指针。这样,在执行函数的过程中可以改变形参指针变量所指向的变量(也就是实参指针所指向的变量)的值。如果函数的形参是指向const型变量的指针,在执行函数过程中显然不能改变指针变量所指向的变量的值,因此,允许实参是指向const变量的指针,或指向非const变量的指针,如:

const char str[] = "wkf";   //str[] 是const 类型的数组

void func(char *ptr);   //函数的形参是非const类型的指针

fun(str);   //非法,实参是const类型,而函数的参数类型不是

       因为形参是指向非const类型变量的指针变量,按理说,在执行函数过程中它所指向的变量的值是可以改变的。但是形参指针和实参指针指向的是同一变量,而实参是const变量的地址,它指向的变量的值是不可改变的。这就发生矛盾。因此C++要求实参用非const变量的地址(或指向非const变量的指针变量)。

       以上介绍的是指向常变量的指针变量,指向常对象的指针变量的概念和使用是与此类似的,只要将“变量”换成“对象”即可。

(1) 如果一个对象已被声明为常对象,只能用指向常对象的指针变量指向它,而不能用一般的(指向非const类型对象的)指针变量去指向它。

(2) 如果定义了一个“指向常对象”的指针变量,并使它指向一个非const的对象,则其指向的对象是不能通过指针来改变的,如下是一个测试例子:

       程序运行结果如下:

       此时,定义了 ps 指针对象是 const 类型,设置指向stud对象。那么,ps指向一个常对象。所以,通过ps不可以修改指向对象的成员。那么,执行 ps->print(); 语句的时候,为了避免在print()函数中修改对象成员,所以,需要把print()定义为const类型。

       那么,修改main()函数如下:

       编译异常,编译信息如下:

wkf@ubuntu:~/c++$ g++ test.cpp -o exe

test.cpp: In function ‘int main()’:

test.cpp:29: error: assignment of data-member ‘student::number’ in read-only structure

       此时,提示ps->number = 139;语句错误,student::number是 read-only类型,无法访问。

       注意:指向常对象的指针变量与指向对象的常指针变量在形式上和作用上的区别如下:

student* const p; //指向对象的常指针变量--- const 修饰指针名p,所以,p是常量,它存放的内容不可以修改

const student *p; //指向常对象的指针变量--- const 修饰student,所以,p 指向的student对象是常量,对象的数据不可以修改

       那么,我们可以定义一个指向对象的常指针,修改main()函数,如下:

int main(void)

{

    student stud("wkf","www.mylinux.vip",13926572996);

    student stud1("ABC","china",13926572996);

    student* const p = &stud;

    p = &stud1;

    return 0;

}

       编译提示异常,如下:

wkf@ubuntu:~/c++$ g++ test.cpp -o exe

test.cpp: In function ‘int main()’:

test.cpp:29: error: assignment of read-only variable ‘p’

       可以看到,执行 p = &stud1; 语句错误。提示指针变量p是read-only类型,无法给指针变量p赋值。因为,指针p是常对象的指针变量,初始化设置为指向stud对象。然后,执行:

p = &stud1;

       此时,修改指针变量p的值是异常的。因为,指针变量p是常指针。

(3) 指向常对象的指针最常用于函数的形参,目的是在保护形参指针所指向的对象,使它在函数指向过程中不被修改,如:

void func(const student *p)

{

    if(NULL == p)

        return;

    p->number = 198;    //错误,p指向的是一个常对象,其数据不可以修改

}

int main()

{

    student stud("wkf","www.mylinux.vip",13926572996);

    func(&stud);//调用函数;

    return 0;

}

       这是一个简单的程序段,func()函数的形参 p 是指向student类常对象的指针,实参可以是const或非const类型对象的地址,所以,func(&stud); 语法是正确的。

但是,形参的性质是const student *p 类型,就要求不允许修改 p 所指向的对象的值。因此,在func()函数中企图改变 p 所指向的对象的成员变量是非法的。

       如果形参不是指向 const 类型的student对象的指针变量,函数的定义如下:

void func(student *p);

       那么,stud中成员变量的值可以在func()函数中修改。在前面的程序段中,main()函数中的stud对象虽然没有定义为const类型,但是,由于形参是指向 const 类型的student对象的指针,所以,在调用func(&stud); 的时候,stud就成为只读的对象,而不能被函数修改。

       请记住这样一条规则:当希望在调用函数时对象的值不被修改,就应当把形参定义为指向常对象的指针变量,同时用对象的地址作为实参(对象可以是const或非const型)。如果要求该对象不仅在调用函数过程中不被改变,而且要求它在程序执行过程中都不改变,则应把它定义为const型。

       定义了一个指向常对象的指针变量,是不能通过它改变所指向的对象的值,但是,指针变量本身的值是可以改变的,例如:

int main()

{

    student stud("wkf","www.mylinux.vip",13926572996);

    student stud1("ABC","china",13926572996);

    const student *p = &stud;   //const 修饰student,所以,指针p 指向的student 是常量,其数据不可以修改,但是,指针p 不是常量,它的值可以修改,就是改变它指向被的对象

    p = &stud1; //合法,因为p 的内容可以修改,指向别的对象,只是,它指向的对象的内容不可以修改而已

    return 0;

}

       可以看到,定义了指针变量p,它指向一个常对象。所以,它指向对象的成员不可以修改。但是,指针变量p的值可以修改,所以,它再次可以赋值为stud1对象的地址。

       所以,充分地使用const修饰符,可以对C++类数据进行很好的保护。

韦凯峰 Linux C/C++ 程序设计教程,Linux 系统编程,Openwrt 系统开发,微信:13926572996,QQ:1523520001,博客:www.mylinux.vip

以上是关于C++指向常对象的指针变量的主要内容,如果未能解决你的问题,请参考以下文章

12.3 C++常指针

12.3 C++常指针

12.3 C++常指针

12.3 C++常指针

C++ const 修饰符

C++指向对象成员的指针