2012-02-23 49 views
16

Ai đó có thể giải thích, hoặc chỉ cho tôi một số giải thích, về giá trị R là gì? Tôi không thực sự chắc chắn nó là gì, và dự án của tôi phải kết hợp nó. Dưới đây là một minh chứng về những gì R-Giá trị là (phần Đầu tiên là r_string.hpp):Giá trị R chính xác trong C++ là gì?

#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

bản sao có thể có của [T && có nghĩa là gì trong C++ 11?] (Http://stackoverflow.com/questions/5481539/what-does-t-mean-in-c11) –

+2

bản sao có thể có của [ rvalues, lvalues, xvalues, glvalues ​​và prvalues?] (http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues) –

+0

@Nicol: Anh ấy hỏi về một giá trị , không phải là một tham chiếu rvalue. Vì vậy, tôi thích câu hỏi này tốt hơn. Nhưng hoàn toàn tích cực là một sự lừa gạt. –

Trả lời

24

"Có thể ai đó giải thích, hoặc chỉ cho tôi một số lời giải thích nào, những gì R-Giá trị là? tôi không thực sự chắc chắn nó là gì"

Thuật ngữ vế trái ban đầu được gọi là một biểu hiện đó có thể là trái bên chuyển nhượng. Tương ứng, rvalue (mặc dù khi tôi nhớ thuật ngữ đó không được tiêu chuẩn C89 sử dụng), ban đầu chỉ ngược lại: một biểu thức không thể là phía bên trái của bài tập, nhưng chỉ có thể là bên tay.

C++ 11 phức tạp điều này bằng cách thêm một số thuật ngữ sắc thái hơn, nhưng hãy tập trung vào ý nghĩa C++ 03.

Ví dụ, nếu bạn có

int x; 

sau đó phân x = 42 là OK, vì vậy x là một biểu thức vế trái.

Làm ví dụ phản biện, việc xác nhận x+0 = 42 không được chấp nhận, vì vậy x+0 là biểu thức giá trị.

Và như vậy là biểu thức 2+2, đó là biểu thức giá trị.

Vì vậy, nếu yêu cầu là chương trình của bạn nên bao gồm một giá trị, sau đó chỉ cần viết 2+2 hoặc ví dụ: (nâng cao hơn) 6*7, trong main.

Bản gốc C không có const. Trong C++, với const, bạn phải bỏ qua số const với mục đích chỉ định biểu thức dưới dạng giá trị hoặc giá trị. Điểm quan trọng là khi biểu thức được bảo đảm đề cập đến một đối tượng trong bộ nhớ, một đối tượng có địa chỉ: nếu có thì biểu thức là một giá trị.

Loại tham chiếu ngụ ý lvalue, vì biểu thức loại tham chiếu nhất thiết phải đề cập đến một đối tượng có địa chỉ bộ nhớ, tức là biểu thức đó là một giá trị.

Tuy nhiên, ngoài tham chiếu, không có kết nối giữa loại và lvalue/rvalue. Ví dụ: cả xx+0 là các biểu thức thuộc loại int và chúng mang lại cùng giá trị int. Nhưng trước đây là một biểu thức lvalue, trong khi sau này là một biểu thức rvalue.

Theo nguyên tắc chung, nếu bạn có thể áp dụng toán tử địa chỉ dựng sẵn, thì đó là biểu thức giá trị, và nếu không, đó là biểu thức giá trị.

+3

Định nghĩa của tiêu chuẩn C về "lvalue" có lịch sử rô; các định nghĩa C90 và C99 đều có vấn đề nghiêm trọng. C11 định nghĩa một lvalue là "một biểu thức ... mà có khả năng chỉ định một đối tượng" ("có khả năng" có nghĩa là '* ptr' là một lvalue ngay cả khi' ptr == NULL'). Từ ngữ được sửa đổi của C11 là ý tưởng của tôi.

+0

@KeithThompson: Bạn có biết rằng liên kết bạn có trên hồ sơ SO của bạn đã chết? –

+0

@CamJackson: Cái nào? Các liên kết GitHub và Nghề nghiệp đều hoạt động cho tôi. –

6

Thuật ngữ rvalue xuất phát từ bối cảnh lịch sử của nó --- nó là cái gì mà chỉ có thể đi về phía bên tay phải của một bài tập, như trái ngược với một vế trái mà có thể đi về phía bên trái của một bài tập. Do đó, biến được đặt tên (ví dụ: x) là một giá trị, nhưng một số nguyên bằng chữ (ví dụ: 42) là một giá trị.

Tuy nhiên, trong C++ hiện đại, nó có nhiều sắc thái hơn thế.

Trong C++, rvalue là một đối tượng chưa được đặt tên hoặc là thành viên của đối tượng đó không phải là tham chiếu.

Một số ví dụ:

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 

Trong (1), std::string đối tượng tạm thời được tạo ra từ các chuỗi chữ là một rvalue.

Trong (2), đối tượng được trả lại từ foo() là một giá trị.

Trong (3), bar() trả về tham chiếu để không có giá trị.

Trong (4), đối tượng tạm thời std::string được tạo hoàn toàn từ chuỗi ký tự là một giá trị.

Trong (5), đối tượng X tạm thời là một giá trị, do đó, do đó, thành viên s.

Các biểu thức chẳng hạn như x+3 thường dẫn đến tạm thời, do đó là một giá trị. Tuy nhiên, nếu quá tải toán tử đã được sử dụng để thay đổi kiểu trả về thành tham chiếu, thì kết quả là một giá trị.

Các vấn đề liên quan