C++ 中的 R 值究竟是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9406121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What exactly is an R-Value in C++?
提问by Dave
Could someone explain, or point me to some sort of explanation, of what R-Value is? I'm not really sure what it is, and my project has to incorporate it. Here is a demonstration of what R-Value is(First part is the r_string.hpp):
有人能解释一下,或者给我指出某种解释,什么是 R 值?我不太确定它是什么,我的项目必须合并它。这是 R 值是什么的演示(第一部分是 r_string.hpp):
#include <algorithm>
#include <iostream>
template <typename CHAR_T = char>
class basic_rstring {
public:
typedef CHAR_T value_type;
typedef CHAR_T* pointer_type;
typedef CHAR_T const* pointer_const_type;
private:
pointer_type _data;
std::size_t _length;
public:
basic_rstring() : _data(nullptr), _length(0)
{
std::cout << "Default ctor\n";
}
basic_rstring( pointer_const_type s )
: _data( nullptr )
, _length( 0 )
{
std::cout << "Literal ctor: " << s << std::endl;
_length = strlen( s );
_data = new value_type[ _length + 1 ];
std::copy( s, s + _length + 1, _data );
}
basic_rstring( basic_rstring const& s )
: _data( nullptr )
, _length( s._length )
{
std::cout << "Copy ctor: " << s.c_str() << std::endl;
_data = new value_type [ _length + 1 ];
std::copy( s._data, s._data + s._length + 1, _data );
}
basic_rstring( basic_rstring && s ) //move constructor
: _data( s._data )
, _length( s._length )
{
std::cout << "Move ctor: " << s.c_str() << std::endl;
s._data = nullptr;
s._length = 0;
}
~basic_rstring()
{
if( _data )
std::cout << "dtor: " << _data << "\n";
else
std::cout << "NULL dtor\n";
delete [] _data;
}
basic_rstring& operator = ( basic_rstring const& s );
basic_rstring& operator = ( basic_rstring && s )
{
std::cout << "RValue assignment: " << s.c_str();
if( _data )
std::cout << " deleting...." << std::endl;
else
std::cout << " no delete..." << std::endl;
delete [] _data;
_data = s._data;
s._data = nullptr;
_length = s._length;
s._length = 0;
return *this;
}
pointer_const_type c_str() const { return _data; }
};
template <typename CHAR_T>
basic_rstring<CHAR_T>& basic_rstring<CHAR_T>::operator = ( basic_rstring const& s )
{
std::cout << "Copy assignment: " << s.c_str() << std::endl;
pointer_type newData = new value_type [ s._length + 1 ];
std::copy( s._data, s._data + s._length + 1, newData );
_length = s._length;
delete [] _data;
_data = newData;
return *this;
}
typedef basic_rstring<char> String;
typedef basic_rstring<wchar_t> wString;
#define _SCL_SECURE_NO_WARNINGS
#include "Rstring.hpp"
using namespace std;
#define BOOST_TEST_MODULE move_test
#include <boost/test/unit_test.hpp>
template <typename T_>
void old_swap( T_& a, T_&b )
{
T_ hold = a;
a = b;
b = hold;
}
BOOST_AUTO_TEST_CASE( stuff )
{
String s("Bert");
String t("Ernie");
cout << "Old swap" << endl;
old_swap(s,t);
BOOST_CHECK( !strcmp( "Bert", t.c_str() ) );
BOOST_CHECK( !strcmp( "Ernie", s.c_str() ) );
cout << "New swap" << endl;
swap(s,t);
BOOST_CHECK( !strcmp( "Bert", s.c_str() ) );
BOOST_CHECK( !strcmp( "Ernie", t.c_str() ) );
cout << "\nDone." << endl;
}
回答by Cheers and hth. - Alf
"Could someone explain, or point me to some sort of explanation, of what R-Value is? I'm not really sure what it is"
“有人能解释一下,或者给我一些解释,什么是 R 值?我不太确定它是什么”
The term lvalueoriginally referred to an expression that could be the lefthand side of an assignment. Correspondingly, an rvalue(although as I recall that term was not used by the C89 standard), was originally just the opposite: an expression that could not be the left hand side of an assignment, but that could only be the righthand side.
术语左值最初是指一个表达式,它可以是赋值的左侧。相应地,右值(尽管我记得 C89 标准没有使用该术语)最初正好相反:一个表达式不能是赋值的左侧,但只能是右侧。
C++11 complicated this by adding several more nuanced terms, but let's concentrate on the C++03 meanings.
C++11 通过添加几个更细微的术语使这一点复杂化,但让我们专注于 C++03 的含义。
For example, if you have
例如,如果你有
int x;
then the assignment x = 42
is OK, so x
is an lvalue expression.
那么赋值x = 42
就可以了,x
左值表达式也是如此。
As a counter-example, the assigment x+0 = 42
is not OK, so x+0
is an rvalue expression.
作为反例,赋值x+0 = 42
不正确,x+0
右值表达式也是如此。
And so is the expression 2+2
, it's an rvalue expression.
表达式也是如此2+2
,它是一个右值表达式。
So, if the requirement is that your program should include an rvalue, then just write 2+2
or e.g. (more advanced) 6*7
, in main
.
因此,如果要求是,你的程序应该包括一个右值,然后只写2+2
或如(更先进的)6*7
中main
。
Original C didn't have const
. In C++, with const
, you have to disregard the const
for the purpose of designating an expression as lvalue or rvalue. The critical point is then whether the expression guaranteed refers to an object in memory, an object with an address: if so, then the expression is an lvalue.
原来的 C 没有const
。在 C++ 中,为了将表达式指定为左值或右值const
,您必须忽略const
。关键点是保证的表达式是否引用内存中的对象,一个具有地址的对象:如果是,则表达式是左值。
A reference type implies lvalue, because an expression of reference type is necessarily referring to an object with a memory address, i.e. that expression is an lvalue.
引用类型隐含左值,因为引用类型的表达式必然指向具有内存地址的对象,即该表达式是左值。
However, other than references there's no connection between type and lvalue/rvalue. For example, both x
and x+0
are expressions of type int
, and they yield the same int
value. But the former is an lvalue expression, while the latter is an rvalue expression.
但是,除了引用之外,类型和左值/右值之间没有联系。例如,x
和x+0
都是 type 的表达式int
,它们产生相同的int
值。但前者是左值表达式,而后者是右值表达式。
As a general rule, if you can apply the built-in address operator, then it's an lvalue expression, and otherwise it's an rvalue expression.
作为一般规则,如果您可以应用内置地址运算符,则它是一个左值表达式,否则它是一个右值表达式。
回答by Anthony Williams
The term rvaluederives from its historical context --- it was something that could only go on the Right-hand side of an assignment, as opposed to an lvaluewhich could go on the left-hand side of an assignment. Thus a named variable (e.g. x
) is an lvalue, but a literal integer (e.g. 42
) is an rvalue.
术语右值源自其历史背景——它只能出现在赋值的右侧,而左值只能出现在赋值的左侧。因此,命名变量(例如x
)是左值,而文字整数(例如42
)是右值。
However, in modern C++ it is more nuanced than that.
然而,在现代 C++ 中,它比这更微妙。
In C++, an rvalue is an unnamed object or a member of such an object which is not a reference.
在 C++ 中,右值是一个未命名的对象或一个不是引用的对象的成员。
Some examples:
一些例子:
std::string s;
std::string foo(){ return "foo";}
struct X {
std::string s;
};
std::string& bar() {return s;}
void baz(std::string const& x){}
s=std::string("hello"); // 1
s=foo(); // 2
std::string s2=bar(); // 3
baz("hello"); // 4
s=X().s; // 5
In (1), the temporary std::string
object created from the string literal is an rvalue.
在 (1) 中,std::string
从字符串文字创建的临时对象是一个右值。
In (2), the object returned from foo()
is an rvalue.
在(2)中,返回的对象foo()
是一个右值。
In (3), bar()
returns a reference so there are no rvalues.
在 (3) 中,bar()
返回一个引用,因此没有右值。
In (4), the temporary std::string
object implicitly created from the string literal is an rvalue.
在(4)中,std::string
从字符串文字隐式创建的临时对象是一个右值。
In (5), the temporary X
object is an rvalue, so therefore so is the s
member.
在(5)中,临时X
对象是一个右值,因此s
成员也是。
Expressions such as x+3
typically result in a temporary, which is thus an rvalue. However, if operator overloading has been used to change the return type to a reference, then the result is an lvalue.
诸如此类的表达式x+3
通常会产生一个临时值,因此它是一个右值。但是,如果使用运算符重载将返回类型更改为引用,则结果为左值。
回答by Aka
Rvalue & Lvalue
右值和左值
Before Explaining This two notation let's Check what is Called Movableand Identity
在解释这两个符号之前,让我们检查一下什么叫做Movable和Identity
Identity:- In short anything that has name & we can point to or Reference to know that whether it is same value or Different Value
身份:- 简而言之,任何具有名称的事物,我们都可以指向或参考以了解它是相同的值还是不同的值
Moving:- In short anything whose content can be moved from one place or Memory to Other
移动:- 简而言之,任何内容可以从一个地方或内存移动到另一个地方的东西
Lvalueare those value that has Identity so we can point to it or Reference it, but cannot Move it These are called Classical Values
左值是那些具有标识的值,因此我们可以指向它或引用它,但不能移动它这些被称为经典值
Rvalueare one that are movable (whether has identity or not) these contains temporary values or ADT that support move
右值是可移动的(无论是否具有标识)这些包含支持移动的临时值或 ADT