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 << "=============================" << '\n'; // 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 */

 

原文链接: https://www.cnblogs.com/MasterYan576356467/p/13257365.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    c++分析lvalue和rvalue的代码

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/362906

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午2:37
下一篇 2023年3月2日 下午2:38

相关推荐