1. 程式人生 > >C++ 判斷左值和右值 (使用程式碼判斷)

C++ 判斷左值和右值 (使用程式碼判斷)

C++的左值和右值的概率繼承自C語言裡。C++11之後引入右值。

左值和右值的根本區別就是左值可以使用&取地址,而右值是不可以取地址的。還有一點就是,右值是可以賦值給左值,但是反過來就不行,即左值不能賦值給右值。通俗的講,就是左值在=左邊,右值在右邊。

其實我們如果在判斷左值和右值的時候,抓住上面的概念,在程式碼裡是非常容易判斷左值和右值的,但是假如讓我們使用程式碼去判斷左值和右值我們又該如何做呢?

在最初的時候,我的想法是取地址的這種辦法,但是如果取的是左值還ok,但是如果我們取右值的話,就會直接報錯。這樣編譯都無法通過。所以使用這種辦法是不太合適的。

在C++裡引入了另外一個和右值相關的概念,就是右值引用。首先我先簡單介紹一下右值引用。

右值引用一般指向的是臨時物件,即即將被銷燬的物件。

作為一種追求執行效率的語言,C++在用臨時物件或函式返回值給左值物件賦值時的深度拷貝(deep copy)一直受到詬病。考慮到臨時物件的生命期僅在表示式中持續,如果把臨時物件的內容直接移動(move)給被賦值的左值物件,效率改善將是顯著的。這就是移動語義的來源。

與傳統的拷貝賦值運算子(copy assignment)成員函式、拷貝構造(copy ctor)成員函式對應,移動語義需要有移動賦值(move assignment)成員函式、移動構造(move ctor)成員函式的實現機制。可以通過函式過載來確定是呼叫拷貝語義還是移動語義的實現。

右值引用就是為了實現移動語義與完美轉發所需要而設計出來的新的資料型別。移動語義是為了提高效率,避免臨時構造物件。二完美轉發主要是廣泛應用於泛型函式。

我使用程式碼去判斷左值和右值其實也是利用了右值引用的這個優點來實現的。具體看下面程式碼

#include <stdio.h>
#include <string>

void print(const std::string& name) {
    printf("rvalue detected:%s\n", name.c_str());
}

void print(std::string& name) {
    printf("lvalue detected:%s\n", name.c_str());
}

int main() {
    std::string name = "lvalue";
    print(name); //compiler can detect the right function for lvalue
    print("rvalue"); // likewise for rvalue
}

其實是非常巧妙的