用于表达式和变量的C ++类型和值类别 [英] C++ Type and Value Category for Expression and Variable
问题描述
通过此链接,它表示
对象,引用,包括函数模板专门化功能在内的函数和表达式具有名为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屋!