• C++ 新特性 笔记


    摘录

    constexptr

    C++14尝鲜:constexpr函数(编译期函数)

    总结来说,就是在c++11之前,要实现编译期数值计算需要繁琐的模板元编程。在c++11 中,可以是函数,在一句ruturn 语句中进行求值,函数中既不能有变量也不能有分之判断语句,限制较多。在C++17之后,则取消了大部分限制,比如可以有变量,可以有分支判断语句,但不能有goto,asm,try等语句。具体可以参考cppreference

    准确的说,constexpr函数是一种在编译期和运行期都能被调用并执行的函数。出于constexpr函数的这个特点,在C++11之后进行数值计算时,无论在编译期还是运行期我们都可以统一用一套代码来实现。编译期和运行期在数值计算这点上得到了部分统一。

    什么是rvalues,lvalues,xvalues,glvalues和prvalues?

    • lvalue(所谓的,历史上,因为左值可以出现在赋值表达式的左侧)表示一函数或一个对象。 [示例:如果E是指针类型的表达式,则*E 是一个左值表达式,引用要指向的对象或函数E 。另一个例子,调用返回类型为左值引用的函数的结果是左值。
    • xvalue(一个“到期”值)也指一个对象,通常接近其寿命的末尾(使得其资源可以被移动,例如)。xvalue是涉及rvalue引用的某些表达式的结果。 [示例:调用返回类型为右值引用的函数的结果是xvalue。]
    • glvalue (“广义”左值)是左值 或x值。
    • rvalue(所谓的,历史上,因为右值可以出现在赋值表达式的右手侧)是x值,临时对象或子对象,或它们的不与一个对象相关联的值。
    • prvalue(“纯”右值)是一个rvalue,这不是一个x值。 [示例:调用返回类型不是引用的函数的结果是prvalue]

    lvalue 左值

    当且仅当E指的是已经具有使其可在E外部访问的标识(地址,名称或别名)的实体时,表达式E属于左值类别。

    #include <iostream>
    
    int i=7;
    
    const int& f(){
        return i;
    }
    
    int main()
    {
        std::cout<<&"www"<<std::endl; // This address ...
        std::cout<<&"www"<<std::endl; // ... and this address are the same.
        "www"; // The expression "www" in this row is an **lvalue expression**, because it refers to the same entity ...
        "www"; // ... as the entity the expression "www" in this row refers to.
    
        i; // The expression i in this row is an lvalue expression, because it refers to the same entity ...
        i; // ... as the entity the expression i in this row refers to.
    
        int* p_i=new int(7);
        *p_i; // The expression *p_i in this row is an lvalue expression, because it refers to the same entity ...
        *p_i; // ... as the entity the expression *p_i in this row refers to.
    
        const int& r_I=7;
        r_I; // The expression r_I in this row is an lvalue expression, because it refers to the same entity ...
        r_I; // ... as the entity the expression r_I in this row refers to.
    
        f(); // The expression f() in this row is an lvalue expression, because it refers to the same entity ...
        i; // ... as the entity the expression f() in this row refers to.
    
        return 0;
    }
    

    xvalues 亡值

    若表达式E属于xvalue类别,当且仅当它满足:
    -无论是隐式调用还是显示调用,调用一个函数的结果返回一个对要返回的对象类型的引用的rvalue

    
    int&& f(){
        return 3;
    }
    
    int main()
    {
        f(); // 表达式 f() 是xvalue ,因为 f() 的返回类型是一个对象类型的引用的 rvalue.
    
        return 0;
    }
    

    -或者,右值(rvalue)引用对象类型的cast

    int main()
    {
        static_cast<int&&>(7); // 表达式static_cast<int&&>(7) , 其是右值引用对象类型的 cast.
        std::move(7); // std::move(7) is equivalent to static_cast<int&&>(7).
    
        return 0;
    }
    

    -类成员访问表达式指定 非引用类型的非静态数据成员, 其中对象表达式是 xvalue

    struct As
    {
        int i;
    };
    
    As&& f(){
        return As();
    }
    
    int main()
    {
        f().i; //  f().i  是 xvalue, 因为 As::i 是 non-static data member of non-reference type, and the subexpression f() belongs to the xvlaue category.
    
        return 0;
    }
    
    • 一种pointer-to-member表达式, 其中第一个操作数是 xvalue, 第二个操作数是指向数据成员的指针。
      请注意,上述规则的效果是对命名rvalue引用被视为lvalues,对对象的未命名rvalue引用被视为xvalues; 对函数的右值引用被视为左值,无论是否命名。
    #include <functional>
    
    struct As
    {
        int i;
    };
    
    As&& f(){
        return As();
    }
    
    int main()
    {
        f(); // The expression f() belongs to the xvalue category, because it refers to an unnamed rvalue reference to object.
        As&& rr_a=As();
        rr_a; //  rr_a 是 lvalue category,因为它指的是一个命名的 rvalue 对象引用
        std::ref(f); // n std::ref(f) 表达式是 lvalue , 因为它指的是一个命名的 rvalue 对象引用
    
        return 0;
    }
    

    prvalue

    当且仅当E既不属于左值也不属于xvalue类别时,表达式E属于prvalue类别。

    struct As
    {
        void f(){
            this; // this  是 **prvalue** 表达式。 注意:this 不是一个变量
        }
    };
    
    As f(){
        return As();
    }
    
    int main()
    {
        f(); // f() 表达式属于 prvalue category, 其既不属于 lvalue 也不属于 xvalue 类
    
        return 0;
    }
    

    rvalue

    当且仅当E属于xvalue类别或属于prvalue类别时,表达式E属于rvalue类别。
    请注意,此定义表示当且仅当E指的是没有任何标识使其可在E之外访问的实体时,表达式E属于右值类别。

    glvalues

    当且仅当E属于lvalue类别或xvalue类别时,表达式E属于glvalue类别。

    一个实用的规则
    Scott Meyers 已出版的经验的一个非常有用的规则,从左值右值的区别。

    如果可以获取表达式的地址,则表达式为左值。
    如果表达式的类型是左值引用(例如,T&或const T&等),则该表达式是左值。
    否则,表达式是右值。从概念上(通常也是实际上),rvalues对应于临时对象,例如从函数返回的或通过隐式类型转换创建的临时对象。大多数文字值(例如,10和5.3)也是右值。

  • 相关阅读:
    Google Analytics:为链接点击设定事件追踪的方法
    HTTP状态码大全
    jquery插件的编写
    2016.2.27日(开学)学习总结
    关于单文件上传的封装
    单文件的文件上传详细解释
    php中对象的串行化
    PDO的事物处理机制
    MySQL操作类的封装(PHP)
    smarty的简单介绍
  • 原文地址:https://www.cnblogs.com/gardenofhu/p/10076205.html
Copyright © 2020-2023  润新知