2.3.2节练习
练习2.18:编写代码分别更改指针的值以及指针所指对象的值。
出题思路:本题旨在考查指针的含义,以及指针本身的值与指针所指对象值的区别,重点掌握解引用运算符的使用方法。
解答:
一个满意要求的简单示例如下所示:
#include <iostream>
int main()
{
int i = 5 j = 10;
int *p = &i;
std::cout << p << " " << *P << std::endl;
p = &j;
std::cout << p << " " << *P << std::endl;
*p = 20;
std::cout << p << " " << *P << std::endl;
j = 30;
std::cout << p << " " << *P << std::endl;
return 0;
}
程序的输出结果是:
0x28fef8 5
0x28fef4 10
0x28fef4 20
0x28fef4 30
在上述示例中,首先定义了两个整数变量i和j以及一个整型指针p,初始情况下令指针p指向变量i,此时分别输出p的值(即p所指对象的内存地址)以及p所指对象的值,得到0x28fefe8和5。
随后依次更改指针的值以及指针所指对象的值。p = &j;更改了指针的值,令指针p指向另外一个整数对象j。*p = 20;和j = 30;是两种更改指针所指对象值的方式,前者显式地更改指针p所指的内存,后者则通过更改变量j的值实现同样的目的。
练习2.19:说明指针和引用的主要区别。
出题思路:指针和引用同为复合类型,都与内存中世纪存在的对象有联系。本题旨在考查二者的主要区别。
解答:
指针“指向”内存中的某个对象,而引用“绑定到”内存中的某个对象,它们都实现了对其他对象的间接访问,二者的区别主要有两方面:
第一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以指向几个不同的对象;引用不是一个对象,无法令引用重新绑定到另外一个对象。
第二,指针无须在定义时赋初值,和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值;引用则必须在定义时赋初值。
练习2.20:请叙述下面这段代码的作用。
int i = 42;
int *p1 = &i;
*p1 = *p1 * *p1;
出题思路:本题旨在考查运算符*的两种含义:一是指针声明符,二是解引用运算符。
解答:
这段代码首先定义了一个整型变量i并设其初值为425;接着定义了一个整型指针p1,令其指向变量i;最后去除p1所指的当前值,计算平方后重新赋给p1所指的对象i。
第二行的*表示声明一个指针,第三行的*表示解引用运算,即取出指针p1所指对象的值。
练习2.21:请解释下属定义。在这些定义中有非法的吗?如果有,为什么?
int i = 0;
(a) double* dp = &i; (b) int *ip = i; (c) int *p = &i;
出题思路:本题旨在考查指针的声明和定义。
(a)是非法的,dp是一个double指针,而i是一个int变量,类型不匹配。
(b)是非法的,不能直接把int变量赋给int指针,正确的做法是通过取地址运算&i得到变量i在内存中的地址,然后再将该地址赋给指针。
(c)是合法的。
练习2.22:假设p是一个int型指针,请说明下述代码的含义。
if (p) // ...
if (*p) // ...
出题思路:本题旨在考查指针的值与指针所指对象的值的区别,巧妙之处是把p和*p作为if语句的条件,通过判断其是否为真帮助读者加深理解。
解答:
指针p作为if语句的条件时,实际检验的是指针本身的值,即指针所指的地址值。如果指针指向一个真实存在的变量,则其值必不为0,此时条件为真;如果指针没有指向任何对象或者是无效指针,则对p的使用将引发不可预计的结果。
解引用运算符*p作为if语句的条件时,实际检验的是指针所指的对象内容,在上面的示例中是指针p所指的int值。如果该int值为0,则条件为假;否则,如果该int值不为0,对应条件为真。
一个简单的示例如下所示:
#include <iostream>
int main()
{
int i = 0;
int *p1 = nullptr;
int *p = &i;
if (p1) // 检验指针的值(即指针所指对象的地址)
std::cout << "p1 pass" << std::endl;
if (p) // 检验指针的值(即指针所指对象的地址)
std::cout << "p pass" << std::endl;
if (*p) // 检验指针所指对象的值
std::cout << "i pass" << std::endl;
return 0;
}
在这段程序中,p和p1是两个整型指针,其中p1被定义为空指针(nullptr),p则指向整数i。在3个判断条件中,p1指向为空,意即指向地址为0,条件不满足;p指向i,在内存中有一个实际的地址且不为0,因此该条件满足;*p表示p所指对象的内存,即整数i的值,因为程序开始处i被赋予了初值0,所以这个条件不满足。
综合以上分析,程序的输出结果是p pass。
练习2.23:给定指针p,你能知道它是否指向了一个合法的对象吗?如果能,叙述判断的思路;如果不能,也请说明原因。
出题思路:本题旨在考查指针初始化,读者应该熟悉并掌握C++11的新语法特征nullptr。
解答:
在C++程序中,应该尽量初始化所有指针,并且尽可能等定义了对象之后再定义指向它的指针。如果实在不清楚指针应该指向何处,就把它初始化为nullptr或者0,这样程序就能检测并知道它有没有指向一个具体的对象了。其中,nullptr是C++11新标准刚刚引入的一个特殊字面值,它可以转换成任意其他的指针类型。再此前提下,判断p是否指向合法的对象,只需把p作为if语句的条件即可,如果p的值是nullptr,则条件为假;反之,条件为真。
如果不注意初始化所有指针而贸然判断指针的值,则有可能引发不可预计的结果。一种处理的办法是把if(p)置于try结构中,当程序块顺利执行时,表示p指向了合法的对象;当程序块出错跳转到catch语句时,表示p没有指向合法的对象。
练习2.24:在下面这段代码中为什么p合法1p非法?
int i = 42; void *p = &i; long *1p = &i;
出题思路:本题旨在考查void*指针的含义和用法。
解答:
p是合法的,因为void*是一种特殊的指针类型,可用于存放任意对象的地址。
1p是非法的,因为1p是一个长整型指针,而i只是一个普通整型数,二者的类型不匹配。
普通的冒险故事提示您:看后求收藏(卧龙小说网http://www.wolongxs.com),接着再看更方便。
好书推荐:《我的剧本世界在自主运行》、《我是舰娘》、《交错世界之学院都市》、《认清现实后,她们开始追夫火葬场》、《好徒儿你就饶了为师伐》、《剑来》、《带着修真界仙子们天下无敌》、《修炼成仙的我只想养成女徒弟》、《足控勇者的目标是魔王的丝袜》、《被触手怪养大的少女》、