CPP & Value Category

前言:

为什么要翻译这篇文章呢?答案是官网提供的中文版简直就是不能看,所以当了搬运工。我感觉这篇文章挺好的,虽然讲的不是那么易懂,有些地方有点晦涩。但是作为参考文档还是可行的。翻译了几段,因为英语不是很好,有些地方可能表达的不到位甚至是错误,希望大神告诉我,我好改进。现在就开始后悔当初没好好学习英语,很多能看懂的东西却不会表达,所以翻译相对比较渣。有能力的还是建议看英文,以免对您形成误导。

原文链接

Value categories(值类别)

Each C++ expression (an operator with its arguments, a literal, a variable name, etc) is characterized by two independent properties: a type and a value category. Each expression has some non-reference type, and each expression belongs to exactly one of the three primary value categories.


每个C++ 表达式(带参数的操作,字面量,变量名)的特征是有两个独立的属性,一个是类型另一个是值。每个表达式有一些非引用类型并且必定属于三种基础值类型之一。

Primary categories

1.lvalue

An lvalue is an expression that identifies a non-temporary object or a non-member function.

左值是这样的一个被标识为非临时对象或者非成员函数的表达式。

The following expressions are lvalues:

The name of a variable or function in scope, regardless of type, such as std::cin or std::endl. Even if the variable’s type is rvalue reference, the expression consisting of its name is an lvalue expression.

作用域中的变量名,函数。例如cin等。甚至变量的类型是右值引用类型只要它具名那么就是左值。

Function call or overloaded operator expression if the function’s or overloaded operator’s return type is an lvalue reference, such as std::getline(std::cin, str) or std::cout << 1 or str1 = str2 or ++iter

函数调用或者某些重载操作,只要他们的的返回类型是左值引用类型,那么也是左值。

Built-in pre-increment and pre-decrement, dereference, assignment and compound assignment, subscript (except on an array xvalue), member access (except for non-static non-reference members of xvalues, member enumerators, and non-static member functions), member access through pointer to data member if the left-hand operand is lvalue, comma operator if the right-hand operand is lvalue, ternary conditional if the second and third operands are lvalues.

大意是内置的前置递增递减操作符作用的对象得到的结果也是左值。

Cast expression to lvalue reference type.

转换成左值引用类型的表达式也是左值。

String literal

String 字面值。

Function call expression if the function’s return type is rvalue reference to function type (rare)

如果函数的返回类型是右值引用类型,那么函数调用表达式可以是一个左值。比较少见。

Cast expression to rvalue reference to function.

转换成右值引用类型的函数表达式。

(since C++11)

Properties:(属性)

Same as glvalue (below)

同glvae一致。

Address of an lvalue may be taken: &++i[1] and &std::endl are valid expressions.

可以被取址。

A modifiable lvalue may be used as the left-hand operand of the built-in assignment operator.

可修改的左值可以被当作内置赋值操作符的左操作数(对象)

An lvalue may be used to initialize an lvalue reference; this associates a new name with the object identified by the expression.

左值可以用来初始化一个左值引用,相当于给左值起了一个别名。

rvalue (until C++11) / prvalue (since C++11)

A prvalue** (“pure” rvalue)** is an expression that identifies a temporary object (or a subobject thereof) or is a value not associated with any object.

纯右值是这样的一个表达式:被视为临时对象或者是在其中的子对象抑或是没有同任何对象关联的值。

The following expressions are prvalues:

下面表达式都是纯右值:

Literal (except string literal), such as 42 or true or nullptr.

字面值,例如42,true,nullptr.

Function call or overloaded operator expression if the function’s or the overloaded operator’s return type is not a reference, such as str.substr(1, 2) or str1 + str2

函数调用的返回类型不是引用类型,例如str.substr(1,2)或者str1+str2.不清楚substr函数的可以去查一下函数原型。

Built-in post-increment and post-decrement , arithmetic and logical operators, comparison operators, address-of operator, member access for a member enumerator, a non-static member function, or a non-static non-reference data member of an rvalue, member access through pointer to a data member of rvalue or to a non-static member function, comma operator where the right-hand operand is rvalue, ternary conditional where either second or third operands aren’t lvalues.

内置的后置自增自减操作符,算术运算符,逻辑运算符等操作符作用下得到的结果是纯右值。

Cast expression to any type other than reference type.

把表达式转换成引用类型之外的其他任何类型。

Lambda expressions, such as [](int x){return x*x;}

Lambda表达式也是纯右值,不清楚的可以参考前面的博文。

(since C++11)

Properties:

Same as rvalue (below)

同右值一致。

a prvalue cannot be polymorphic: the dynamic type of the object it identifies is always the type of the expression.

纯右值不可能是多态的。它被认为的动态类型总是表达式的类型

a non-class prvalue cannot be cv-qualified.

非类 纯右值不可能是局部cv-qualified 的。cv表示const/volatile ,.

a prvalue cannot have incomplete type (except for type void, see below, or when used in decltype specifier)

纯右值不可能是不完全类型。除了下文介绍的void类型。

xvalue

An xvalue is an expression that identifies an “eXpiring” object, that is, the object that may be moved from. The object identified by an xvalue expression may be a nameless temporary, it may be a named object in scope, or any other kind of object, but if used as a function argument, xvalue will always bind to the rvalue reference overload if available.

xvalue 值是这样的一种类型:被视为将要消失的对象,也就是说这个对象将要被移走。这个对象可能是匿名临时对象,也可能是在某作用域中的具名对象或者其他类型的对象。但是当xvalue被用作一个函数的参数时,xvlaue总是被绑定到右值引用类型,前提是存在这样的一个函数并且形参是右值引用类型。

Only the following expressions are xvalues:(只有下面的表达式是xvalues).

A function call or overloaded operator expression if the function’s or the overloaded operator’s return type is an rvalue reference to object type, such as std::move(val)

A cast expression to an rvalue reference to object type, such as static_cast

Mixed categories(混合类别)

glvalue

A glvalue (“generalized” lvalue) is an expression that is either an lvalue or an xvalue.

既不是左值或者xvalue类型就是gvalue.

Properties (note: these apply to pre-C++11 lvalues as well)

A glvalue may be implicitly converted to prvalue with lvalue-to-rvalue, array-to-pointer, or function-to-pointer implicit conversion.

A glvalue may be polymorphic: the dynamic type of the object it identifies is not necessarily the static type of the expression.

A glvalue can have incomplete type, where permitted by the expression

rvalue

An rvalue is an expression that is either a prvalue or an xvalue.

Properties (note, these apply to both xvalues and prvalues, which means they apply to the pre-C++11 rvalues as well)

Address of an rvalue may not be taken: &int(), &i++[2], &42, and &std::move(val) are invalid.

Rvalues can’t be used as the left-hand operand of the built-in assignment or compound assignment operator.

An rvalue may be used to initialize a const lvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.

An rvalue may be used to initialize an rvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends.

When used as a function argument and when two overloads of the function are available, one taking rvalue reference parameter and the other taking lvalue reference to const parameter, rvalues bind to the rvalue reference overload (thus, if both copy and move constructors are available, rvalue arguments invoke the move constructor, and likewise with copy and move assignment operators).

(since C++11)

Special categories(特殊类别)

Pending member function call

The expressions obj.func and ptr->func, where func is a non-static member function, and the expressions obj.*mfp and ptr->*mfp where mfp is a pointer to member function, are classified as prvalue expressions, but they cannot be used to initialize references, as function arguments, or for any purpose at all, except as the left-hand argument of a function call expression, e.g. (pobj->*ptr)(args).

Void expressions

Function call expressions returning void, cast expressions to void, and throw-expressions are classified as prvalue expressions, but they cannot be used to initialize references or as function arguments. They can be used in some contexts (e.g. on a line of its own, as the left argument of the comma operator, etc) and in the return statement in a function returning void. In addition, throw-expressions may be used as the second and the third operands of the conditional operator ?: (other void prvalues can only be used if appearing as both 2nd and 3rd operands).

Bit fields

An expression that designates a bit field (e.g. s.x where s is an object of type struct S { int x:3; };) is an lvalue expression (or xvalue if s is one): it may be used on the left hand side of the assignment operator, but its address cannot be taken and a non-const lvalue reference cannot be bound to it. A const lvalue reference can be initialized from a bit-field lvalue, but a temporary copy of the bit-field will be made: it won’t bind to the bit field directly.

footnotes

↑ Assuming i has built-in type or the pre-increment operator is overloaded to return by lvalue reference

↑ Assuming i has built-in type or the postincrement operator is not overloaded to return by lvalue reference

时间: 2024-08-05 08:30:02

CPP & Value Category的相关文章

深入理解Objective-C:Category

摘要 无论一个类设计的多么完美,在未来的需求演进中,都有可能会碰到一些无法预测的情况.那怎么扩展已有的类呢?一般而言,继承和组合是不错的选择.但是在Objective-C 2.0中,又提供了category这个语言特性,可以动态地为已有类添加新行为.如今category已经遍布于Objective-C代码的各个角落,从Apple官方的framework到各个开源框架,从功能繁复的大型APP到简单的应用,catagory无处不在.本文对category做了比较全面的整理,希望对读者有所裨益. 简介

Objective-c Category(类别)

category是Objective-c里面最常用的功能之一. category可以为已经存在的类增加方法,而不需要增加一个子类. 类别接口的标准语法格式如下: [cpp] view plaincopy #import "类名.h" @interface 类名 (类别名) //新方法的声明 @end 类别实现如下: [cpp] view plaincopy #import "类名类别名.h" @implementation 类名 (类别名) //新方法实现 @end

Objective-C分类 (category)和扩展(Extension)

1.分类(category) 使用Object-C中的分类,是一种编译时的手段,允许我们通过给一个类添加方法来扩充它(但是通过category不能添加新的实例变量),并且我们不需要访问类中的代码就可以做到,这点和javascript中使用原型来定义属性有点类似. 我们可以为一个类创建一个新的方法,而不需要在代码中编辑类定义. 下面就是定义并使用分类的例子程序,通过下面代码,我们可以给Object-C中的NSString 添加camelCaseString分类,使用camelCaseString方

iOS runtime探究(四): 从runtiem开始实践Category添加属性与黑魔法method swizzling

你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639335 本文主要讲解runtime相关知识,从原理到实践,由于包含内容过多分为以下五篇文章详细讲解,可自行选择需要了解的方向: 从runtime开始: 理解面向对象的类到面向过程的结构体 从runtime开始: 深入理解OC消息转发机制 从runtime开始: 理解OC的属性property 从runtime开始: 实践Category添加属

细细品味Ubuntu Scope中的category renderer模版

当我第一次接触Ubuntu Scope时,我发现这个Category Renderer太神奇.它可以把我们想要的数据很简单而直接的方式呈现给我们.但是由于资料的限制,我们很难知道它最终的显示的形式是什么样的.我们可以在我们的英文的网站的文章"Customization and branding"找到一下信息.但是总觉得意犹未尽,加之没有代码,有时很难理解它到底讲的是什么.在这篇文章中,我们来详细地介绍各种模版,并看看它们的显示格式.详细这对广大的开发者来说非常有用.我们可以修改这些模版

Objective-C中Extension与Category的使用

Objective-C 2.0增加了class extensions用于解决两个问题: 允许一个对象可以拥有一个私有的interface,且可由编译器验证. 支持一个公有只读,私有可写的属性. 私有接口(Private Interface) Objective-C 2.0以前, 若要定义私有函数,通常是在实现文件中声明一个"Private" category: @interface MyClass (Private)  - (id)awesomePrivateMethod; @end

Cpp Chapter 12: Classes and Dynamic Memory Allocation Part2

12.3 Things to remember when using new in constructors ) If you use new in constructors, use delete in destructor. Their use should be compatible, pair new with delete and new [] with delete [] ) Multiple constructors should share the same way of new

Cpp Chapter 14: Reusing code in C++ Part1

14.1 Classes with object members ) The valarray class To declare an object, you follow the identifier valuearray with angle brackets that contain the desired type: valarray<int> q_values; valarray<double> weights; Several examples that use the

category is in invalid format hint微信第三方平台将第三方提交的代码包提交审核出错

微信第三方平台通过接口https://api.weixin.qq.com/wxa/submit_audit?access_token=TOKEN将第三方提交的代码包提交审核时一直返回错误码85008的错误信息: category is in invalid format hint 查了半天是接口提交数据时json_encode时中文不能编码提交 将向微信的提交代码     $this->https_post($url,json_encode($postData)); 改为     $this->