用于表达式和变量的C ++类型和值类别 [英] C++ Type and Value Category for Expression and Variable

查看:69
本文介绍了用于表达式和变量的C ++类型和值类别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过此链接,它表示

对象,引用,包括函数模板专门化功能在内的函数和表达式具有名为type的属性

Objects, references, functions including function template specializations, and expressions have a property called type

因此,给出以下内容:

int &&rf_int = 10;

我可以说变量 rf_int 具有复合类型对int的右值引用.

I can say that variable rf_int is of compound type rvalue reference to int.

但是在谈论值类别时,它专门说

But when talking about value category, it specifically says that

每个表达式都有一些非引用类型

每个C ++表达式(带有其操作数,文字,变量名称等的运算符)

根据以上两个语句,可以将 rf_int 视为一个表达式,并且该表达式具有非引用类型.

Based on the above two statement, rf_int can be treated as an expression and expression has non-reference type.

现在我真的很困惑. rf_int 是否具有引用类型?在谈论名称的类型时,是否需要提供上下文?是变量还是表达式?

Now I am really confused. Does rf_int have a reference type or not? Do we have to provide context when talking about the type of a name, be it a variable or an expression?

更具体地说,在函数调用中使用变量名时:

More specifically, when a variable name is used in function call:

SomeFunc(rf_int);

rf_int 现在被认为是表达式(因此它是int类型的左值)还是变量(因此它是类型rvalue引用int的左值)?

Is rf_int now considered an expression (thus it is an lvalue with type int), or a variable (thus it is an lvalue with type rvalue reference to int)?

编辑:在此处让我对这个问题感到疑惑.

EDIT: A comment here got me wonder about this issue.

推荐答案

基于

Based on this each function call is an expression. Each argument passed to the function is also an expression.

因此,当您调用 SumFunc(rf_int); 时,将使用单个 rf_int 变量创建一个表达式.

Therefore, when you make a call to SumFunc(rf_int); you create an expression from the single rf_int variable.

ISO/IEC 14882(c ++ 14标准)指出,表达式指定由引用表示的对象或函数,并且表达式取决于表达式,是左值或x值."

ISO/IEC 14882 (c++14 standard) states that "The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression."

因此, rf_int 表达式的类型将为int.

Thus, the rf_int expression will be of type int.

此评论(您之前提到过)与类型有关转换错误.

This comment (you mention it before) is about type conversion error.

为了说明我的解释,我准备了一个更复杂,但(希望)更易于理解的示例.此示例说明为什么我们需要 右值引用 类型以及如何正确使用它.

To illustrate my explanation, I have prepared a more complex, but (hopefully) more understandable example. This example is about why we need rvalue refernce type and how to use it correctly.

class Obj {
    int* pvalue;
public:
    Obj(int m) {
        pvalue = new int[100];
        for(int i = 0; i < 100; i++)
            pvalue[i] = m + i;
    }
    Obj(Obj& o) {  // copy constructor
        pvalue = new int[100];
        for(int i = 0; i < 100; i++)
            pvalue[i] = o.pvalue[i];
    }
    Obj(Obj&& o) {  // move constructor
        for(int i = 0; i < 100; i++)
            pvalue = o.pvalue;
        o.pvalue = nullptr;
    }
   // ...
};

示例1

  Obj obj1(3);
  Obj obj2(obj1);  // copy constructor
  Obj obj3(std::move(obj1)); // move constructor
  Obj obj4(Obj(3)); // move constructor

第1行-已创建obj1.
第2行-obj2创建为obj1的副本
第3行-通过将obj1的值移动到obj3来创建的obj3;obj1失去它的值
第4行-Obj(3)创建的临时对象;通过将临时对象的值移动到obj4来创建obj4;临时对象失去其价值

Line #1 - obj1 created.
Line #2 - obj2 created as a copy of obj1
Line #3 - obj3 created by moving value of obj1 to the obj3; obj1 loose it's value
Line #4 - temporary object created by Obj(3); obj4 created by moving value of temporary object to obj4; temporary object loose it's value

我认为我们并不需要 int&& ,但 Obj& 可能非常有用.尤其是在第4行.

I think we have no real need of int&& but Obj&& can be very useful. Especially in the line #4.

示例2 我对编译器错误的(简化)解释

Example 2 with my (simplified) interpretation of compiler errors

void SomeFunc0(Obj   arg) {};
void SomeFunc1(Obj&  arg) {};
void SomeFunc2(Obj&& arg) {};

int main()
{
  Obj   obj1(3);        // object
  Obj&  obj2 = obj1;    // reference to the object
  Obj&& obj3 = Obj(3);  // reference to the temporary object with extened lifetime


    SomeFunc0(obj1); // ok - new object created from Obj
    SomeFunc0(obj2); // ok - new object created from Obj&
    SomeFunc0(obj3); // ok - new object created from Obj&&
    SomeFunc0(Obj(3)); // ok - new object created from temporary object
    SomeFunc0(std::move(obj1)); // ok - new object created from temporary object
    SomeFunc0(std::move(obj2)); // ok - new object created from temporary object
    SomeFunc0(std::move(obj3)); // ok - new object created from temporary object

    SomeFunc1(obj1); // ok - reference to obj1 passed
    SomeFunc1(obj2); // ok - reference to obj1 passed
    SomeFunc1(obj3); // ok - reference to temp. obj. passed
    SomeFunc1(Obj(3)); // error - lifetime of the temp. obj. too short
    SomeFunc1(std::move(obj1)); // error - lifetime of the temp. obj. too short
    SomeFunc1(std::move(obj2)); // error - lifetime of the temp. obj. too short
    SomeFunc1(std::move(obj3)); // error - lifetime of the temp. obj. too short

    SomeFunc2(obj1); // error - temporary object required
    SomeFunc2(obj2); // error - temporary object required
    SomeFunc2(obj3); // error - lifetime of the temp. obj. too long
    SomeFunc2(Obj(3)); // ok
    SomeFunc2(std::move(obj1)); // ok
    SomeFunc2(std::move(obj2)); // ok
    SomeFunc2(std::move(obj3)); // ok

    return 0;
}

这篇关于用于表达式和变量的C ++类型和值类别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆