2013-06-28 61 views
6

Trong khi tôi đang đọc http://thbecker.net/articles/rvalue_references/section_01.html, tôi nhận được đoạn trích sau.Sự khác biệt chính xác giữa rvalue và lvalue

// lvalues: 
// 
int i = 42; 
i = 43; // ok, i is an lvalue 
int& foo(); 
foo() = 42; // ok, foo() is an lvalue 
int* p1 = &foo(); // ok, foo() is an lvalue 

// rvalues: 
// 
int foobar(); 
int j = 0; 
j = foobar(); // ok, foobar() is an rvalue 
int* p2 = &foobar(); // error, cannot take the address of an rvalue 
j = 42; // ok, 42 is an rvalue 

Tại sao int * p2 = & foobar(); là báo cáo lỗi, trong khi int * p1 = & foo(); không phải là lỗi. Làm thế nào sau đó là lvalue trong khi đầu tiên là rvalue?

Cảm ơn trước

+0

Tôi tin câu cuối cùng của bạn có nó ở phía sau –

Trả lời

4

Vì vậy, chúng ta có hai chức năng:

int& foo(); 
int foobar(); 
  • foo là một hàm trả về giá trị trái-tham chiếu đến int
  • foobar là một hàm trả về int

Biểu thức gọi hàm:

foobar() 
foo() 

cả hai đều có kiểu int (tài liệu tham khảo được loại bỏ từ ngữ, vì vậy foo() có kiểu int và không lvalue-reference to int). Hai biểu thức có loại giá trị khác nhau:

  • foobar() là một prvalue (một cuộc gọi chức năng để một hàm trả về một tổ chức phi tham chiếu là một prvalue)
  • foo() là một giá trị trái (một cuộc gọi chức năng để một hàm trả về một lvalue-reference là một lvalue)

Bạn không thể lấy địa chỉ của một rvalue (giá trị là một loại giá trị), vì vậy không được phép &foobar().

Bạn có thể lấy địa chỉ của một lvalue để &foo() được cho phép.

+0

Tại sao không thể lấy địa chỉ của foo? –

+0

@ ss7don: Bạn có nghĩa là cụm từ 'foo()'? Bạn có thể lấy địa chỉ của 'foo()'. Đọc lại dòng cuối cùng của câu trả lời của tôi. –

+0

Tôi đã chấp nhận câu trả lời vì có vẻ hợp lý. Thành thật mà nói tôi vẫn không hiểu sự khác biệt chính xác giữa foo và foobar. Cả hai đều là hàm. Nhưng làm thế nào một là rvalue và một số khác là lvalue. –

6

Giả sử chúng ta có mã ví dụ được hiển thị bên dưới trong C. Nó có biên dịch không? Làm thế nào để các khái niệm về giá trị và rvalues ​​làm việc trong vấn đề này?

#define X 8 
int main(void) 
{ 
    ++X; // will this line compile? 
     return 0; 

} 

Khái niệm về giá trị và giá trị phải được giải thích một chút để hiểu mã bên trên và vấn đề được hỏi. Trước khi chúng ta tiến hành, bạn nên lưu ý rằng định nghĩa của các giá trị và các giá trị được trình bày ở đây không chính xác vì ngay cả các chuẩn C cũng khá mơ hồ về định nghĩa.

Sự khác biệt giữa giá trị và giá trị

Đối tượng là vùng bộ nhớ có thể kiểm tra nhưng không nhất thiết phải sửa đổi. Một lvalue là một biểu thức đề cập đến một đối tượng như vậy. Thuật ngữ lvalue ban đầu được gọi là các đối tượng xuất hiện ở bên trái (do đó là ‘l’) bên tay của một biểu thức. Định nghĩa đó không còn áp dụng vì bất kỳ loại có đủ điều kiện nào cũng được coi là một giá trị, nhưng nó không bao giờ có thể xuất hiện ở phía bên tay trái của câu lệnh gán bởi vì nó không thể sửa đổi được. Vì vậy, thuật ngữ "lvalue có thể sửa đổi" được tạo ra để tham chiếu đến một giá trị có thể được sửa đổi và một loại có đủ điều kiện không thuộc loại này.

Giá trị là bất kỳ biểu thức nào có giá trị, nhưng không thể gán giá trị cho nó. Người ta cũng có thể nói rằng một rvalue là bất kỳ biểu hiện đó không phải là một lvalue.Một ví dụ về một rvalue sẽ là một hằng số theo nghĩa đen - giống như '8 ′, hoặc' 3,14 ′. Vì vậy, rõ ràng giá trị '8 ′ trong mã ở trên là một giá trị.

Sử dụng sự hiểu biết của chúng ta về lvalues ​​và rvalues ​​để trả lời câu hỏi

Bây giờ chúng ta hãy cố gắng giải quyết vấn đề. Nói đúng ra, toán hạng của toán tử tăng tiền tố (hoặc postfix) phải là một giá trị có thể sửa đổi được. Vì vậy, toán hạng của toán tử tăng thêm tiền tố trong mã của chúng ta ở trên là gì?

Vì X là macro, câu lệnh ở trên sẽ mở rộng thành “++ 8 ″ sau khi bộ tiền xử lý được chạy. Điều này có nghĩa là "8" là toán hạng của toán tử tăng tiền tố. Và, bởi vì 8 là một rvalue nó không thể được sử dụng như một đối số để "+ +". Điều này, đến lượt nó, có nghĩa là mã ở trên sẽ không biên dịch.

+1

Rất đẹp, nhưng tại sao phải bận tâm với ví dụ này? Tôi không thấy làm thế nào loại câu hỏi đố có thể giúp đỡ trong sự hiểu biết về vấn đề này. – SChepurin

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