c++ primer第五版-----学习笔记(四)

1.重载运算符

operator,IO库中>>和<<运算符以及string对象、vector对象和迭代器使用的运算符都是重载的运算符。

2.左值与右值

左值与右值的定义在于一个赋值等号,复制等号左边成为左值,等号右边成为右值

(1)左值(L-value):表示存储在计算机内存中的对象,可寻址,相当于地址值

(2)右值(R-value):代表的为真实值,可读,即数据值

(3)因为左值是一个地址值,因此可以对左值进行赋值操作,而右值本身就是同一个数据值,就不存在对一个数据值进行赋值

(4)一个左值表达式的求值解果是一个对象或一个表达式,以常量对象为代表的某些左值实际上不能作为赋值语句的左侧运算对象

3.求值顺序与处理复合表达式

(1)对于那些没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义行为

int i = 0;
cout << i << " " << ++i << endl;      //未定义的

(2)有四种运算符指定了运算对象的求值顺序(先求左侧运算对象):逻辑与(&&)、逻辑或(||)、条件(?:)、逗号(,)

(3)处理复合表达式:

  • 拿不准的时候最好用括号来强制让表达式的组合关系符合程序逻辑的要求
  • 如果改变了某个运算对象的值,在表达式的其它地方不要再使用这个运算对象

4.部分重点知识

(1)进行比较运算时除非比较的对象是布尔类型,否则不要使用布尔字面值truefalse作为运算对象

(2)因为赋值运算符的优先级低于关系运算符的优先级,所以在条件语句中,赋值部分通常应该加上括号

(3)前置版本的递增运算符避免了不必要的工作,它把值加1后直接返回改变了的运算对象(尽量使用前置递增运算符)

5.条件运算符

(1)基本形式:cond ? expr1 : expr2; 其中cond是判断条件的表达式,expr1和expr2是类型相同的表达式

//普通条件运算符
string finalgrade = (grade < 60) ? "fail" : "pass";
//嵌套条件运算符
string finalgrade = (grade > 90) ? "high pass" :
                                    (grade < 60) ? "fail" : "pass";

(2)条件运算的嵌套最好别超过两到三层

(3)在输出表达式中使用条件运算符注意优先级(最好加上括号区分)

6.位运算符

(1)作用于整数类型的运算对象,并把运算对象看成是二进制位的集合;提供检查和设置二进制位的功能

(2)常用位运算符:

左移运算符     <<          在右侧插入值为0的二进制位
右移运算符     >>          如果对象是无符号类型,在左侧插入值为0的二进制位
                          否则在左侧插入符号位的副本或值为0的二进制位
位求反运算符   `           将运算对象逐位求反
位与运算符     &           两个必须同时为1才为1
位或运算符     |           有1则为1
位异或运算符   ^           相异为1  

(3)使用位运算符:

unsigned long quizl = 0;  //这个值是位的集合
1UL << 27;                //生成一个值,该值只有第27位为1,unsigned long 有32位

7.sizeof运算符

Sales_data data, *p;
sizeof(Sales_data);              //存储Sales_data类型的对象所占的空间大小
sizeof  data;                    //data的类型大小,即sizeof(Sales_data)
sizeof  p;                       //指针所占的空间大小
sizeof  *p;                      //p所指类型的空间大小,即sizeof(Sales_data)
sizeod data.revenue;             //Sales_data的revenue成员对应类型的大小
sizeof Sales_data::revenue;      //另一种获取revenue大小的方式

8.类型转换

类型转换分为两类:

(1)隐式类型转换

(2)显示类型转换

隐式类型转换常见于各种函数的传参,以及不同类型变量间的运算

下面主要介绍显示类型转换:

//命名的强制类型转换,具有如下形式
cast-name<type>(expression)
//cast-name是static_cast、dynamic_cast、const_cast、和reinterpret_cast中的一种

static_cast
//1.任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast
double slope = static_cast<double>(j) / i;       //进行强制类型转换以便执行浮点数除法
//2.当需要把一个较大的算术类型赋值给较小的类型时,static_cast非常有用
//3.static_cast对于编译器无法自动执行的类型转换非常有用
void* p = &d;                            //任何非常量对象的地址都能存入void*
double *dp = static_cast<double*> (p);   //将void*指针转换回初始的类型


const_cast
//1.const_cast只能改变运算对象的底层const
const char *pc;
char *p = const_cast<char*> (pc); //正确:但是通过p写值是未定义的行为
//2.将常量对象转换成非常量对象的行为,被称为去掉const性质
//(只有const_cast能改变表达式的常量属性)

reinterpret_cast     //使用非常危险

//尽量避免使用强制类型转换

9.部分习题解答

4.2:

(a)可改为*(vec.begin())        (b)可改为(*vec.begin() + 1)

4.3:

可以,关键还是编程者自己对于程序的改写

4.7:

溢出的定义:当计算的结果超出了该类型所能表示的最大范围时就会产生溢出

4.10:

int n;
while ((cin >> n) && (n != 42)
{
}

4.12:

算术>关系>逻辑

所以式子等同于:

i != (j < k)

4.14:

if (42 = i)     //将变量赋給常量,判断为假
if (i = 42)     //将42赋給变量i,42非0,为真

4.15:

指针类型不能隐式的转换为int整形

可改为:

dval = ival = *pi = 0;

4.18:

输出第二个元素,直到最后一个元素的下一个位置(程序可能会报错)

4.21:

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> v;
    int n;
    while (cin>>n)
    { 
       	v.push_back(n);
    }
    for (auto &c : v)
    {
	cout << ((c % 2) ? (c * 2) : c) << " ";
    }
    cout << endl;
    system("pause");
    return 0;
}

4.22:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
    int grade;
    cout << "Please input your grade: ";
    cin >> grade;
    string a;
    a =  (grade > 90) ? "high pass" : (grade > 75) ? "pass" : (grade >= 60) ? "low pass" : "fail" ;
    cout << a;
    system("pause");
    return 0;
}

4.25:

对于~ 'q' << 6这个表达式,其意思是先求反后左移,得到结果为1111 1111 1111 1111 1110 0011 1000 0000,其值为-7296

4.29:

sizeof在对数组使用时,返回的是数组的大小;在对指针使用时,返回的是指针本身的大小,所以输出结果为10,1

4.31:

效率问题,后置版本需要保存两个值

4.33:

由编程结果可得:当somevalue = 0时,执行--x,--y;当somevalue为1时,执行++x;

#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
    int x = 0, y = 0,somevalue = 1;
    somevalue ? ++x, ++y : --x, --y;
    cout << x << " " << y;
    system("pause");
    return 0;
}

4.35:

(a)char->int,char->int            (b)int->double,看unsigned int和double所占空间,再到float

(c)看unsigned int 和double所占空间,再到double

(d)int ->float ,float->double, char->int, double->int

4.36:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
    int i = 3;
    double b = 3.14;
    i *= static_cast<double>(b);     //较大的算术类型赋給较小的算术类型
    cout << i << endl;
    system("pause");
    return 0;
}

4.37:

(a)pv = reinterpret_cast<void* >(ps);

(b)i = static_cast<int>(*pc);

(c)pv = reinterpret_cast<void*>(&d);

(d)pc = reinterpret_cast<char*>(pv);

对于reinterpret_cast类型转换不是很理解!!!

4.38:

执行强制转换得到浮点数的除法

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值