2012-02-23 4 views
16

Может кто-нибудь объяснить или указать мне какое-то объяснение того, что такое R-Value? Я не совсем уверен, что это такое, и мой проект должен включить его. Вот демонстрация того, что R-Значение (Первая часть является r_string.hpp):Что такое R-значение в C++?

#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; 

} 
+2

Возможный дубликат [Что означает T && в C++ 11?] (Http://stackoverflow.com/questions/5481539/what-does-t-mean-in-c11) –

+2

Возможный дубликат [Что такое rvalues, lvalues, xvalues, glvalues ​​и prvalues?] (http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues) –

+0

@Nicol: Он спрашивает о rvalue , а не ссылку rvalue. Поэтому мне нравится этот вопрос лучше. Но абсолютно положительно обман. –

ответ

24

«Может кто-нибудь объяснить, или указать мне на какое-то объяснение, того, что R-Value является? Я не совсем уверен, что это»

термин именующего первоначально относилось к выражению, которое может стать оставило стороны уступки. Соответственно, rvalue (хотя, насколько я помню, термин не использовался стандартом C89), изначально было просто противоположным: выражение, которое не могло быть левой стороной задания, но это может быть только справа стороны.

C++ 11 усложнил это, добавив еще несколько нюансных терминов, но давайте сосредоточимся на значениях C++ 03.

Например, если у вас есть

int x; 

того задание x = 42 ОК, так x является именующим выражением.

В качестве встречного примера, адрес x+0 = 42 не в порядке, поэтому x+0 - выражение rvalue.

И вот выражение 2+2, это выражение rvalue.

Итак, если требование заключается в том, что ваша программа должна включать значение r, тогда просто напишите 2+2 или, например, (более продвинутый) 6*7, в main.

Original C не имеет const. В C++, с const, вы должны игнорировать const с целью обозначения выражения как lvalue или rvalue. Критической точкой является то, является ли гарантированное выражение ссылкой на объект в памяти, объект с адресом: если это так, то выражение является lvalue.

Тип ссылки подразумевает lvalue, поскольку выражение ссылочного типа обязательно относится к объекту с адресом памяти, то есть это выражение является значением lvalue.

Однако, кроме ссылок, нет связи между типом и значением lvalue/rvalue. Например, как x, так и x+0 являются выражениями типа int, и они дают то же значение int. Но первое является выражением lvalue, в то время как последнее является выражением rvalue.

Как правило, если вы можете применить встроенный оператор адреса, то это выражение lvalue, и в противном случае это выражение rvalue.

+3

Определение стандарта «lvalue» стандарта C имеет проверочную историю; определения C90 и C99 имели серьезные проблемы. C11 определяет lvalue как «выражение ... которое потенциально обозначает объект» («потенциально» означает, что '* ptr' является lvalue, даже если' ptr == NULL'). Пересмотренная формулировка C11 была моей идеей.

+0

@KeithThompson: Знаете ли вы, что ссылка, которую вы имеете на свой SO-профиль, мертва? –

+0

@CamJackson: Какой? Связи GitHub и Careers работают для меня. –

6

Термин Rvalue вытекает из исторического контекста --- это было что-то, что могло пойти только на правой стороне уступки, в отличие от Lvalue, которые могли бы пойти на левой стороне задания. Таким образом, именованная переменная (например, x) является значением lvalue, но буквальное целое число (например, 42) является значением rvalue.

Однако в современном C++ он более тонкий, чем этот.

В C++ rvalue является неназванным объектом или членом такого объекта, который не является ссылкой.

Некоторые примеры:

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 

В (1), временный std::string объект, созданный из строки буквального является Rvalue.

В (2) объект, возвращенный с foo(), является rvalue.

В (3) bar() возвращает ссылку, поэтому нет значений.

В (4) временный объект std::string, неявно созданный из строкового литерала, является rvalue.

В (5) временный объект X является rvalue, поэтому он также является членом s.

Выражения, такие как x+3, обычно приводят к временному, что, таким образом, является значением rvalue. Однако, если перегрузка оператора была использована для изменения возвращаемого типа на ссылку, то результатом является значение lvalue.