C++ Primer学习笔记之第四章--表达式

4、1 基础

4.1.1 基本概念
1、左值和右值
(1)C++的表达式要不然是右值(rvalue),要不然就是左值(lvalue)
(2)一个重要原则:在需要右值的地方可以用左值来替代,但不能把右值当成左值使用(有一种情况例外,可以把右值当成左值使用)。
(3)当一个对象被用作右值的时候,用的对象的值(内容),当对象被用作左值的时候,用的是对象的身份(在内存中的位置)
(4)需要用到左值的运算符
①赋值运算符(需要一个非常量左值)
②取地址符
③内置解引用运算符、下标运算符。
④内置类型和迭代器的递增减运算符

4.1.2 优先级与结合律
1、复合表达式(compound expression):是指含有两个或多个运算符的表达式。
(1)括号可以无视优先级和结合律。

4.1.3 求值顺序
1、有四种运算符明确规定了运算符对象的求值顺序
(1)&&
(2)||
(3)?:
(4),

4.3节练习
4.10:为while循环写一个条件,使其从标准输入中读取整数,遇到42时候停止。

int a;
    while (cin >> a&&a != 42)
        cout << a << endl;

4.11:书写一条表达式用于测试4个值a、b、c、d的关系,确保a大于b、b大于c、c大于d

int a = 4, b = 3, c = 2, d = 1;
    if (a > b&&b > c&&c > d)
        cout << "a>b,b>c,c>d" << endl;

4.4 赋值运算符

1、赋值运算符满足右结合律
2、赋值运算表达式优先级比较低,所以在条件语句中,赋值部分通常应该加上括号。

4.5 递增和递减运算符

1、
(1)前置版本(++i):先将运算对象加(减1),然后将改变后的对象作为求值结果。
(2)后置版本(i++):先将对象作为求值结果,再给运算对象加1(或减1)

2、运算对象可按任意顺序求值

4.7条件运算符

1、格式:

condition?expr1:expr2

(1)condition为真,执行expr1
(2)condition为假,执行expr2

2、条件运算符可嵌套

3、条件运算符的优先级非常低,因此当一条长表达式中嵌套了(?:),通常需在两端加上括号。

4、7节练习
4.21:编写一段程序,使用条件运算符从vector中找到哪些元素的值是奇数,然后将这些奇数值

int a;
    std::vector<int> iv;
    while(cin>>a)
        iv.push_back(a);
    for(auto:vi)
        cout<<((i%2==0)?0:i*2);

4.22:用条件运算符版本将学生成绩分为fail、low pass、pass、high pass四个阶层。

int grade;
    cout<<"Enter grade:\n";
    cin>>grade;
    cout<<(grade<60?"fail":(grade<75?"low pass":(grade<90?"pass":"high pass")))<

用if语句写的版本

int grade;
    cout<<"Enter grade: ";
    cin>>grade;
    if(grade<60)
        cout<<"fail"<else if(grade<75&&grade>60)
        cout<<"low pass"<else if(grade>75&&grade<90)
        cout<<"pass"<else
        cout<<"high pass"<

4.8 位运算符

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

2、bitset类型,其标准库类型也可以表示任意大小的二进制位集合。

3、位运算符(满足左结合律)
(1)~(位求反)
<1>格式:
~expr

(2)<<(左移) >>(右移)
<1>格式:
expr1<
expr1>>expr2

(3)&(位与)
<1>格式:
expr1&expr2

(4)^(位异或)
<1>格式:
expr^expr

(5)|(位与)
<1>格式:
expr|expr

4、位运算符(又叫IO运算符)满足左结合律

4.9 sizeof运算符

1、作用:返回一条表达式或一个类型名所占的字节数
2、格式:
(1)

sizeof (type);
size expr;

3、sizeof运算符可获取类成员大小而无须提供一个具体的对象。

4.11 类型转换 ##

1、隐式转换(implicit conversion):由编译器自动执行的类型转换(自动执行,无须程序员介入。)
2、发生隐式转换的情况
(1)比int类型小的整型值受限提升为较大的整数类型
(2)在条件中,非布尔值转换成布尔类型
(3)初始化过程中,初始值(literal)转换成变量类型
(4)赋值语句中,右侧运算符转换成左侧运算符
(5)算术运算符或关系运算符有多种类型的时候
(6)函数调用的时候

4.11.3 显式转换
1、命名的强制类型转换(cast)
(1)格式: cast-name(expression)
<1>type:转换的目标类型
<2>expression:要转换的值
<3>type若是引用类型,则结果是左值
<4>cast-name是以下4种类型
①static_const
②dynamic_cast
③const_cast
④reinterpret_cast
中的一种

(2)static_cast:任何具有明确定义的类型转换,只要不包含底层const,都可以使用。
<1>例:

double slope=static_cast<double>(j)/i;

<2>优点:较大算术类型转换为较小算术类型。

(3)const_cast:只能改变运算对象的底层const
<1>例:

const char c='k';
char *pc=&c;
char *p=const_cast<char *>(pc);
//正确,但是通过p写值是未定义的行为 

<2>优点:const_cast能去掉底层const,将一个指向常量的指针转换为一个指向不一定是常量的指针。

(4)reinterpret_cast:通常为运算对象的位模式提供较低层次上的重新解释(一般用于不同类型的指针转换)
<1>例:

int *ip;
char *pc=reinterpret_cast<char *>ip;
//pc所指向的对象为int而非字符
string str(pc);     //运行时发生错误   

2、旧式的强制类型转换
(1)格式:

type(expr);     //函数形式的强制类型转换
(type)expr;     //C风格的强制类型转换

4.11.3节练习
4.36:假设i是int类型,d是double类型,书写表达式i*=d使其执行整数类型的乘法而非浮点类型的乘法

int i=1;
    double d=1.234;
    i*=static_cast<double>(d);
    i*=d;
    cout<

4.37:用命名的强制类型转换改写下列旧式的转换语句

int i;
double d;
const string *ps;
char *pc;void *pv;

(a)pv=(void *)ps;
    pv=static_cast<void *>(const_cast<string *>(ps));

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

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

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

你可能感兴趣的:(表达式,C++primer学习笔记)