C++Primer 第5版 第2章 变量和基本类型 习题2.15-2.29

2.3 复合类型

2.3.1 引用

练习2.15

下面哪个定义是不合法的?为什么?

 ( a ) int ival = 1.01; 
 ( b )int &rvall = 1.01;  
 ( c )int &rvall2 = ival;   
 ( d )int &rval3;  

 (b)是非法的,引用必须指向一个实际存在的对象而非字面值常量。

(d)是非法的,无法另引用重新绑定到另外一个对象上,所以引用必须初始化。

(a)和(c)是合法的。

练习2.16

考察下面的所有赋值然后回答:哪些赋值是不合法的?为什么?哪些赋值是合法的?它们执行了哪些操作?

int i = 0, &r1 = i; double d = 0, &r2 = d;
- (a) r2 = 3.14159;
- (b) r2 = r1;
- (c) i = r2;
- (d) r1 = d;

 (a)是合法的,为引用赋值实际上是把值赋给了与引用和绑定的对象,在这里3.14159赋给了d。

(b)是合法的,以引用作为初始值实际上是以引用绑定的对象作为初始值,在这里将i的值赋给了变量d。会执行自动转换(int -> double)

(c)是合法的,把d的值赋给了变量i,因为d是双精度浮点数而i是整数,所以该语句实际上执行了窄化操作。

(d)是合法的,把d的值赋给了变量i,与上一条语句一样执行了窄化操作。

#include <iostream>
using namespace std;
int main() {
	int i = 0, &r1 = i;
	double d = 0, &r2 = d;
	
	cout << "When r2 = 3.14159:" << endl;
	r2 = 3.14159;
	cout << "d = " << d << endl;
	cout << "r1 = " << r1 << endl;
	cout << "r2 = " << r2 << endl;
	cout << "i = " << i << endl;

	cout << "When r2 = r1:" << endl;
	r2 = r1;
	cout << "d = " << d << endl;
	cout << "r1 = " << r1 << endl;
	cout << "r2 = " << r2 << endl;
	cout << "i = " << i << endl;

	cout << "When i = r2:" << endl;
	i = r2;
	cout << "d = " << d << endl;
	cout << "r1 = " << r1 << endl;
	cout << "r2 = " << r2 << endl;
	cout << "i = " << i << endl;

	cout << "When r1 = d:" << endl;
	r1 = d;
	cout << "d = " << d << endl;
	cout << "r1 = " << r1 << endl;
	cout << "r2 = " << r2 << endl;
	cout << "i = " << i << endl;

}
// When r2 = 3.14159:
// d = 3.14159
// r1 = 0
// r2 = 3.14159
// i = 0
// When r2 = r1 :
//	d = 0
//	r1 = 0
//	r2 = 0
//	i = 0
//	When i = r2 :
//	d = 0
//	r1 = 0
//	r2 = 0
//	i = 0
//	When r1 = d :
//	d = 0
//	r1 = 0
//	r2 = 0
//	i = 0

练习2.17

 执行下面的代码段将输出什么结果?

int i, &ri = i;
i = 5; ri = 10;
std::cout << i << " " << ri << std::endl;

 引用不是对象,它只是为已经存在的对象起了另外一个名字,因此ri实际上是i的别名。在上述程序中,首先将i赋值为5,然后把这个值更新为10。因为ri是i的引用,所以它们输出是一样的。

#include <iostream>
using namespace std;
int main() {
	int i, &ri = i;
	i = 5; ri = 10;
	std::cout << i << " " << ri << std::endl;
}
//10 10

 2.3.2 指针

练习2.18

编写代码分别改变指针的值以及指针所指对象的值。

#include<iostream>
using namespace std;
int main()
{
	int i= 5, j = 10;
	int *p = &i;
	cout << p << " " << *p << endl;
	p = &j;
	cout << p << " " << *p << endl;
	*p = 20;
	cout << p << " " << *p << endl;
	j = 30;
	cout << p << " " << *p << endl;
	return 0;
}
//0096F74C 5
//0096F740 10
//0096F740 20
//0096F740 30

练习2.19

说明指针和引用的主要区别。

指针和引用都属于符合类型。都与内存中实际存在的对象有联系。指针''指向''内存中的某个对象,而引用''绑定到''内存中的某个对象,它们都实现了对其他对象的间接访问,二者的主要区别主要有两个方面:

(1)指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以指向几个不同的对象;引用不是一个对象,无法令引用重新绑定到另外一个对象。

(2)指针无需在定义时赋初值,和其他内置类型一样,在块作用域内定义的指针没有被初始化,也将拥有一个不确定的值;引用必须在定义时赋初值。

练习2.20

请叙述下面这段代码的作用。

int i = 42;
int *p1 = &i; 
*p1 = *p1 * *p1;

让指针 pi 指向 i,然后将 i 的值重新赋值为 42 * 42 (1764)。其中第二行的*表示声明一个指针,第三行的*表示解引用运算,即取出指针p1所指对象的值。

#include<iostream>
using namespace std;
int main()
{
	int i = 42;
	int *p1 = &i;
	*p1 = *p1 * *p1;
	cout << "*p1 = " << *p1 << endl;
	return 0;
}
//*p1 = 1764

练习2.21

请解释下述定义。在这些定义中有非法的吗?如果有,为什么?

int i = 0;
(a) double* dp = &i;
(b) int *ip = i;
(c) int *p = &i;

(a)是非法的,dp是double指针,而i是一个int性变量,类型不匹配。

(b)是非法的,不能将 int 变量赋给指针。正确的做法是通过取址运算&i得到变量i在内存中的地址,然后再将该地址赋给指针。

(c)是合法的。

练习2.22

假设 p 是一个 int 型指针,请说明下述代码的含义。

if (p) // ...
if (*p) // ...

指针p作为if语句的条件时,实际检验的是指针本身的值,即指针所指的地址值。 判断 p 是不是一个空指针。

解引用运算符*p作为if语句的条件时,实际检验的是指针所指的对象内容,在上面所指的是指针p所指的int值。如果int值为0,则条件为假,否则,如果该int值不为0,对应条件为真。

#include<iostream>
using namespace std;
int main()
{
	int i = 0;
	int *p1 = nullptr;
	int *p = &i;
	if (p1) //检验指针的值(即指针所指对象的地址)
		cout << "p1 pass" << endl;
	if(p)   //检验指针的值(即指针所指对象的地址)
		cout << "p pass" << endl;
	if(*p)   //检验指针所指对象的值
		cout << "i pass" << endl;
	return 0;
}
//p pass

练习2.23

给定指针 p,你能知道它是否指向了一个合法的对象吗?如果能,叙述判断的思路;如果不能,也请说明原因。

练习2.24

在下面这段代码中为什么 p 合法而 lp 非法? 

int i = 42;
void *p = &i;
long *lp = &i;

 p是合法的,因为void*是一种特殊的指针类型,可用于存放任意对象的地址。

lp是非法的,上面的例子已经说过,这种属于类型不匹配的错误。

 2.3.3理解符合类型的声明

练习2.25

说明下列变量的类型和值。

(a) int* ip, i, &r = i;

(b) int i, *ip = 0;

(c) int* ip, ip2;

 (a)ip是一个整型指针,指向一个整型数,它的值是所指整型数再内存中的地址;i是一个整型数;r是一个引用,它绑定了i,可以看作是i的别名,r的值就是i的值。

(b)i是一个整型数;ip是一个整型指针,但是它不指向任何具体的对象,它的值被初始化为0。

(c)ip是一个整型指针,指向一个整型数,它的值是所指整型数再内存中的地址;ip2是一个整型数。

2.4 const限定符

练习2.26

下面哪些语句是合法的?如果不合法,请说明为什么?

(a) const int buf;      
(b) int cnt = 0;       
(c) const int sz = cnt; 
(d) ++cnt; ++sz;        

 (a)是非法的,const对象必须初始化,可以改为const int buf=12;

(b)是合法的。

(c)是合法的。

(d)是非法的,sz是一个const对象,其值不能被改变,当然不能执行自增操作。

2.4.1 const的引用

2.4.2 const和指针

练习2.27

下面的哪些初始化是合法的?请说明原因。

int i = -1, &r = 0;         
int *const p2 = &i2;        
const int i = -1, &r = 0;  
const int *const p3 = &i2;  
const int *p1 = &i2;        
const int &const r2;         
const int i2 = i, &r = i;         

练习2.28

说明下面的这些定义是什么意思,挑出其中不合法的。

int i, *const cp;       
int *p1, *const p2;     
const int ic, &r = ic;  
const int *const p3;    
const int *p;        

练习2.29

假设已有上一个练习中定义的那些变量,则下面的哪些语句是合法的?请说明原因。

i = ic;     
p1 = p3;    
p1 = &ic;   
p3 = &ic;   
p2 = p1;    
ic = *p3;   

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙有肥鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值