4-表达式

  • 基础

    • 运算符包含一元运算符和二元运算符,具体含义要按照上下文决定;
    • 运算符重载:对于内置类型和复合类型,用户自己所定义的符号重载的行为;
    • 对于重载运算符来说,运算对象的类型以及返回值的类型都是运算符定义的,但是不能够改变运算对象的个数,运算符的优先级以及结合律;
    • 建议使用()来使运算符的结合顺序符合要求;
    • 如果这个表达式改变了某个对象的值,那么在这个表达式里面就不要再使用这个对象;for(;;)循环是个例外;
  • 关于左值和右值

    • 对于C语言:
      • 左值来说,左值可以在等号的左边以及右边,但是右值只能够在等号的右边;
    • 对于C++语言:

      • 需要右值的地方可以使用左值来代替,但是不能够把右值当成左值来使用;
      • 当左值被当作右值来使用时,实际上使用的是它的值;
      • 赋值运算符需要一个左值作为其左侧的运算对象,得到的结果也仍然是一个左值;
      • &取地址运算符作用于一个左值运算对象,返回一个指向该运算对象的指针,得到的结果是一个右值;
      • 内置解引用运算符:
      • 下标运算符:
      • 迭代器运算符:
      • stringvector下标运算符得到的结果都是左值:
      • 内置类型和迭代器的自增,自减运算符作用于左值运算对象,得到的结果仍然是左值;
        //需要左值的几种情况
        //赋值运算符的左值
        int ix = 12;
        int nix = ix;
        //对于ix来说,可以出现在等号的左边或者是右边,等式1的ix使用的是地址空间,等式2的
        //ix使用的是里面的12的值;
        //nix以及ix本质上都是左值,但是ix被用右边;
        //取地址运算符
        int *pix = &nix;
        //nix是一个左值,但是pix是一个右值,因为在使用pix时,使用的是pix对象的值;
        //内置解引用运算符
        *pix;
        //*pix的得到的结果可以出现在等号的右边,也可以出现在等号的左边,是左值;
        ix = *pix;
        *pix = ix;
        //下标运算符:
        string mystring{"Hello,world"};
        mystring.[i]可以出现在等号的左边,同时也可以出现在等号的右边;
    • 对于decltype,如果作用于左值表达式得到的死引用类型;

    • 运算对象的求值顺序和优先级和结合律无关;
      int i=12;
      cout << i << ++i << endl;
      //结果根据编译器而定;
  • 两种运算的等价

    • 除数和被除数符号不一样时,有负为负,m%-n等价于m%n,(-m)%n等价于-(m%n);
    • 对于赋值运算符,表达式的值,就是执行赋值时所赋的值;
    • 赋值运算符从右往左进行赋值运算;
    • C++建议使用前缀的自增自减操作,原因有:
      • 前置版本将对象本身作为左值返回,后置对象将对象原始值的副本作为右值返回;
      • 前置可以避免对于原始对象进行复制的资源浪费,尤其是对于大规模的复杂迭代器;
      • 后置还可能出现对于数组下表的越界访问;
      • 后缀操作多用于需要在使用当前值之后进行自增操作;
    • expr1 逻辑运算符 expr2 ? expr1 : expr2 条件运算符不应该超过两层到三层;
    • 在输出表达式中使用条件表达式,应该使用(),否则输出的结果可能不理想;
    • 位运算符应该用于无符号类型;
    
    #include<iostream>
    
    using namespace std;
    int main(){
        cout << "21%6: " << 21%6 << endl; 
        cout << "21/6: " << 21/6 << endl; 
        cout << "21%7: " << 21%7 << endl; 
        cout << "21/7: " << 21/7 << endl; 
        cout << "-21%-8: " << -21%-8 << endl; 
        cout << "-21/-8: " << -21/-8 << endl; 
        cout << "21%-5: " << 21%-5 << endl; 
        cout << "21/-5: " << 21/-5 << endl; 
        cout << "-21%5: " << -21%5 << endl; 
    }
    • C++11允许使用花括号括起来的初始值列表作为等号的右侧对象;

      k = {3.14};
    • 赋值运算符满足右结合律,int ival,nival; ival=nival=0;;

  • 位运算符
运算符功能
~按位求反
<<向左移位,放大
>>向右移位,缩小
&位与运算符
^位异或运算符
``
unsigned char bits=0233;
bits << 8;
bits << 11;
bits << 12;
bits = ~bits;
unsigned char b1 = 0145;
unsigned char b2 = 0245;
int next = b1 & b2;
int next1 = b1 | b2;
int next2 = b1 ^ b2;
  • 左移位运算符向右插入0用于扩大数的位数,右移运算符,无符号左侧插入0,有符号符号位或者0;
  • sizeof运算符
    • 满足有右结合率,返回值类型是size_t类型;
    • sizeof(*p),在这个过程中是不会对p进行解引用操作的,即使p是一个无效的指针,也不会出错;
    • C++11允许无需提供具体的对象可以直接获得类成员的大小;
    • 对于char或者类型是char的表达式得到的结果是1;
    • 对引用执行sizeof得到的是被引用对象所占有空间的大小;
    • 对指针执行sizeof得到的是指针本身空间的大小;
    • 对解引用指针执行sizeof得到的是指针指向的对象所占有的空间的大小,指针不需要进行解引用;
    • 对数组执行sizeof运算符得到的是整个数组所占空间的大小,sizeof不会将数组转换成指针来进行处理;
    • string对象或者vector对象执行sizeof运算只会返回该类型固定范围的大小,不会计算对象中的元素占有了多少空间;
  • 逗号运算符
    • 从左向右一次求值,并且丢弃左边的值,将右边的值作为表达式的值;
  • 类型转换
    • 左值只能在等号右边,右值可以在等号的左边或者右边;
    • 隐式转换
      • 隐式转换进最大可能的避免损失精度;
      • 在初始化过程中,初始值被转换成变量的类型,在赋值语句中右侧对象转换成左侧对象类型;
      • 数组转换成指针,数组自动被转换成数组首元素的指针;
      • 指针转换:常量整数值0或者是字面值nullptr转换成任意指针类型;
      • 执行任意非常量的指针能够转换成void*,指向任意对象的指针都能够转换成const void*
      • 转换成bool类型,存在一种从算术类型自动转换成bool类型,0转换成false,否则转换成true;
      • 转换成常量:允许将常量指针转换成对应的常量指针,对于引用来说也是这样;
      • 在函数进行调用时,需要将函数转为函数指针来进行调用;
    • 算术转换
      • 整型提升,通常是将小类型提升为大类型,这样进行转换没有太大的精度损失,对于较小的char,signed char,unsigned char,unsigned char,short,unsigned short,在保证数据精度的情况下,通常会转换为int类型;
    • 显示的类型转换
      • 关于命名的强制类型转换,cast_name<type>(expression),cast_name具有以下几种形式:
        • static_cast:对于任何具有明确类型的转换,只要不包含底层const是都可以进行转换的,主要用于将高精度的类型转换为小精度的类型时,可以用于忽略警告,还可以用于编译器无法转换的类型;

          //对于这段代码来说,强制进行类型转换和不进行强制类型转换的结果是一样的;
          int i=10;
          int j=2.1;
          double slope = static_cast<double> j/i;
          double slope1 = j/i;
          //上面两个的输出结果都是5;
          //对于底下,没有static_cast是会出错的;
          void *pi = &i;
          double *dpi = static_cast<double*>(pi);
        • const_cast:只能够用于改变运算对象的底层const,这个以后解释;
    • *
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值