• c++分析lvalue和rvalue的代码


    核心代码取自http://www.talkplayfun.com/

    概念来源于: 1.维基百科 2.上述网站的建立者 3.C++.Templates.The.Complete.Guide.2nd(第一版是零几年的,第二版好像没有中文版,嗯,好像。。。)

    光通过“看”去区分lvalue和rvalue可能难以真正明白这些概念的,所以这个时候就需要从代码的角度看看这些概念到底是什么玩意。

    一些说明:

    1. 翻译不一定准确 sorry for my broken English...

     2. decltype(a) 返回的是a的类型(type category), decltype((a)) 返回的是a的值类型(value category) 二者并不等价

    3. 在c++中,值本身是有类型的,比如 int a = 0; a的类型是int, a的值类型是int&,二者类型并不一致

    4. 在c++中,lvalue和rvalue是value category, lvalue reference和rvalue reference是type category 二者并不是一个东西

    5. 值可以细分为三个类型:lvalue(左值), xvalue(亡值? 貌似是说生命周期非常短), prvalue(纯右值, 比如一些字面量), 其中lvalue和xvalue叫做泛左值(glvalue), prvalue和xvalue叫做右值(rvalue)

    6. 左值是可以取地址的,亡值通常生命周期极短, 纯右值包括一些字面量如0,1,2,3...,但不包括字符串,比如“hello world”

    剩下的看看英文吧

    /**
     *                           expression category
     *                              /          
     *                          glvaue         rvalue
     *                      /               /       
     *                     lvalue       xvalue      prvalue
     */
    // lvalue: an expression that has an identity and which we can take address of
    
    // xvalue: "eXpiring lvalue" - an object that we can move from, which we can
    // reuse. Usually, its lefetime ends soon
    
    // prvalue: pure rvalue - something without a name, which we cannot take the
    // address of, we can move from such expression (just as initialization) -> move
    // and copy will be elided
    
    // glvalue: "generalised lvalue" - A glvalue is an expression whose evaluation
    // computers the location of an object, bit field, or function
    
    /**
     * class X { int a; };
     * X{10}; -> prvalue
     * X x; -> lvalue
     * x.a; -> lvalue
     * X xx = CreateX(); -> prvalue
     */
    
    #include <iostream>
    #include <string>
    #include <type_traits>
    
    template <typename T>
    constexpr bool is_lvalue_helper = std::is_lvalue_reference_v<T>;
    
    template <typename T>
    constexpr bool is_xvalue_helper = std::is_rvalue_reference_v<T>;
    
    template <typename T>
    constexpr bool is_prvalue_helper =
        !(is_lvalue_helper<T> || is_xvalue_helper<T>);
    
    template <typename T>
    constexpr bool is_rvalue_helper = is_xvalue_helper<T> || is_prvalue_helper<T>;
    
    template <typename T>
    constexpr bool is_glvalue_helper = is_xvalue_helper<T> || is_lvalue_helper<T>;
    
    #define Is_Lvalue(type_instance) is_lvalue_helper<decltype((type_instance))>
    #define Is_Xvalue(type_instance) is_xvalue_helper<decltype((type_instance))>
    #define Is_PRvalue(type_instance) is_prvalue_helper<decltype((type_instance))>
    #define Is_Rvalue(type_instance) is_rvalue_helper<decltype((type_instance))>
    
    template <typename T>
    std::string type_to_str() {
        /*
        #if defined(_MSC_VER)
            std::string type_name(__FUNCSIG__);
        #elif defined(__GNUC__)
            std::string type_name(__PRETTY_FUNCTION__);
        #elif defined(__clang__)
            std::string type_name(__PRETTY_FUNCTION__);
        #endif
        */
        // __GNUC__
        // std::string type_to_str() [with T = int; std::string =
        // std::basic_string<char>]
        std::string s{__PRETTY_FUNCTION__};
        auto start = 36;
        auto end = s.find_first_of(';', start);
        return s.substr(start, end - start);
    }
    
    #define GetTypeCategory(type_instance) type_to_str<decltype(type_instance)>()
    #define GetValueCategory(type_instance) type_to_str<decltype((type_instance))>()
    
    #define STRING(STR) #STR
    
    #define Print_Value_Info(type_instance)                    
        std::cout << STRING(type_instance) << " is prvalue ? " 
                  << Is_PRvalue(type_instance) << std::endl;   
        std::cout << STRING(type_instance) << " is xvalue  ? " 
                  << Is_Xvalue(type_instance) << std::endl;    
        std::cout << STRING(type_instance) << " is lvalue  ? " 
                  << Is_Lvalue(type_instance) << std::endl;    
        std::cout << STRING(type_instance) << " is rvalue  ? " 
                  << Is_Rvalue(type_instance) << std::endl
    
    auto f = [](int x) { return x; };
    int c = 0;
    void test1() {
        std::cout.setf(std::ios::boolalpha);
    
        std::cout << GetTypeCategory(c) << std::endl;
        std::cout << GetValueCategory(c) << std::endl;
        std::cout << GetValueCategory(f) << std::endl;
        std::cout << GetTypeCategory(f) << std::endl;
    }
    
    void test2() {
        int a = 0;
        int& r_a = a;
        int&& rr_a = 0;
    
        Print_Value_Info(a);
        Print_Value_Info(r_a);
        Print_Value_Info(rr_a);
    
    }
    
    struct X { int a; };
    X CreateX(){
      return {};
    };
    void test3() { /** * class X { int a; }; * X{10}; -> prvalue * X x; -> lvalue * x.a; -> lvalue * X xx = CreateX(); -> prvalue */ std::cout.setf(std::ios::boolalpha); X x; std::cout << Is_PRvalue(X{10}) << std::endl; std::cout << Is_Lvalue(x) << std::endl; std::cout << Is_Lvalue(x.a) << std::endl; std::cout << Is_PRvalue(CreateX()) << std::endl; } int main(int argc, char const* argv[]) { std::cout << "=============================" << ' '; // test1(); // test2(); test3(); return 0; } /* int a = 2; // a's declared type is int and its value category is lvalue // 2 has no declared type, but its deduced type is int and its value // category is prvalue int& r = a; // r's declared type is lvalue reference and value category is lvalue int&& rr = 5; // rr's declared type is rvalue reference and value category is lvalue // 5 -> int, its value category is prvalue // decltype() return type category // decltype( () ) return value category An expression is C++ has two category type category and value category lvalue reference, rvalue reference value category - if we can assign or access or modify the expression lvalue, prvalue, xvalue, glvalue, rvalue usually in CPU register */
  • 相关阅读:
    Linux 守护进程创建
    Linux 进程
    静态库与动态库的制作
    目录文件的操作函数 mkdir ,opendir,readdir,closedir
    获取文件或目录的属性 stat 函数
    文件IO 例子
    文件 IO
    标准 IO fread 与 fwrite 的使用(可以实现二进制流的读写)
    bzoj 2716: [Violet 3]天使玩偶
    cf1175 DE
  • 原文地址:https://www.cnblogs.com/MasterYan576356467/p/13257365.html
Copyright © 2020-2023  润新知