zoukankan      html  css  js  c++  java
  • C++进阶--理解左值和右值

    /*
     * 理解左值和右值
     *
     *
     * 为什么要关心这个?
     * 1. 有助于理解C++结构,搞明白编译器的错误和警告
     * 2. C++ 11中引入了右值引用,理解左值右值是前提
     *
     */
    
    
    /*
     * 简单的定义:
     *
     * 左值 - 在内存中具有可标识位置的对象
     * 右值 - 任何不是左值的对象
     */
    
    
    //左值的例子:
    int i;        // i是左值
    int* p = &i;  // i的地址是可标识的
    i = 2;    // 内存的内容改变
    
    class dog;
    dog d1;   // 用户定义类型的左值
                // C++代码中大多数变量是左值
    
    
    //右值的例子:
    int x = 2;        // 2是右值
    int x = i+2;      // (i+2)是右值
    int* p = &(i+2);  // Error,地址不可标识
    i+2 = 4;     // Error 地址不可标识
    2 = i;       // Error
    
    dog d1;
    d1 = dog();  // dog()是用户定义类型的右值
    
    int sum(int x, int y) { return x+y; }
    int i = sum(3, 4);  // sum(3, 4) 是右值
    
    //右值: 2, i+2, dog(), sum(3,4), x+y
    //左值: x, i, d1, p
    
    
    //引用 (或者说左值引用):
    int i;
    int& r = i;
    
    int& r = 5;      // Error,引用不能赋值为左值,需要可标识的地址
    
    //例外:常量左值引用可以赋值为右值
    const int& r = 5;   //
    
    
    // 函数中的例子
    int square(int& x) { return x*x; }
    square(i);   //  OK
    square(40);  //  Error
    
    //解决方法:
    int square(const int& x) { return x*x; }  // square(40) and square(i) work
    
    
    
    /*
     * 左值可以用来生成右值
     */
    int i = 1;
    int x = i + 2; 
    
    int x = i;
    
    
    /*
     * 右值可以用来生成左值
     */
    int v[3];
    *(v+2) = 4;
    
    
    /*
     * 误解1:函数或运算符总是产生右值
     */
    int x = i + 3;  
    int y = sum(3,4);
    
    int myglobal ;
    int& foo() {
       return myglobal;
    }
    foo() = 50;
    
    // 更常见的例子:
    array[3] = 50;  // 操作符[] 几乎总是返回左值
    
    
    
    /*
     * 误解2:左值都是可以修改的
     *
     */
    const int c = 1;  // c是左值
    c = 2;   // Error, 但是c不能被修改
    
    
    
    /*
     * 误解3:右值不能被修改
     */
    i + 3 = 6;    // Error,内置类型的确不行
    sum(3,4) = 7; // Error
    
    // 对于用户定义类型不成立
    class dog;
    dog().bark();  // dog()是右值,bark() 可能修改dog对象的状态
    
    
    
    /*
     * 总结
     *
     * 1. 每个C++表达式生成一个左值或右值
     * 2. 如果表达式有一个可以标识的内存地址,则它是左值;否则,是右值
     */
    
  • 相关阅读:
    使用SignalR实现即时通讯功能
    SignalR入门篇
    Mongodb关闭开源许可感想
    RaspberryPi学习教程系列4(串口通信篇)
    RaspberryPi学习教程系列3(编程实验篇-双色LED实验)
    RaspberryPi学习教程系列1(系统安装篇)
    RaspberryPi学习教程系列2(编程前准备篇)
    关于Entity Framework,园里有非常多误人子弟的`
    Java多线程1:使用多线程的几种方式以及对比
    Django编写RESTful API(六):ViewSets和Routers
  • 原文地址:https://www.cnblogs.com/logchen/p/10171805.html
Copyright © 2011-2022 走看看