程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> [C++11]_[初級]_[左值引用聲明和右值引用聲明]

[C++11]_[初級]_[左值引用聲明和右值引用聲明]

編輯:關於C++

場景:

在 remove_reference 結構體中能看到右值引用的身影 &&, 那麼這裡的右值引用到底有什麼用呢? 經常也發現int& 和int&& 這兩種類似的應用類型,第一種是左值引用聲明,第二種是右值引用聲明. 以下的例子直接參考的 cppreference,已經寫的很完整了,沒必要重新寫.

語法

左值引用聲明: & attr(optional) declarator (1)
右值引用聲明: && attr(optional) declarator (2) (since C++11)

左值引用聲明 &

–1. 左值引用可以理解為對象的別名, 左值引用必須被初始化而且不能被重新賦值.

#include 
#include 

int main()
{
    std::string s = "Ex";
    std::string& r1 = s;
    const std::string& r2 = s;

    r1 += "ample";           // modifies s
//  r2 += "!";               // error: cannot modify through reference to const
    std::cout << r2 << '\n'; // prints s, which now holds "Example"
}

–2. 在調用函數時,可以被用來作為引用參數.

#include 
#include 

void double_string(std::string& s)
{
    s += s; // 's' is the same object as main()'s 'str'
}

int main()
{
    std::string str = "Test";
    double_string(str);
    std::cout << str << '\n';
}

–3. 當一個函數的返回值是左值時, 這個函數的調用的表達式可以被認為是一個左值表達式.


#include 
#include 

char& char_number(std::string& s, std::size_t n)
{
    return s.at(n); // string::at() returns a reference to char
}

int main()
{
    std::string str = "Test";
    char_number(str, 1) = 'a'; // the function call is lvalue, can be assigned to
    std::cout << str << '\n';
}

右值引用聲明 &&

–1. 右值引用聲明可以區別一個左值和右值.
–2. 右值引用直至Move語義的實現, 它可以把臨時對象(一般不能引用)的資源移動到其他地方去.

–3. 右值引用也可以用來擴展臨時對象的生命周期,

#include 
#include 

int main()
{
    std::string s1 = "Test";
//  std::string&& r1 = s1;           // error: can't bind to lvalue

    const std::string& r2 = s1 + s1; // okay: lvalue reference to const extends lifetime
//  r2 += "Test";                    // error: can't modify through reference to const

    std::string&& r3 = s1 + s1;      // okay: rvalue reference extends lifetime
    r3 += "Test";                    // okay: can modify through reference to non-const
    std::cout << r3 << '\n';
}

–4. 如果函數有左值和右值引用的重載,調用時會匹配調用, 傳左值調用左值重載, 右值調用右值重載. 這樣就可以支持Move Constructor 和 Move Assignment 的實現.

#include 
#include 

void f(int& x)
{
    std::cout << "lvalue reference overload f(" << x << ")\n";
}

void f(const int& x)
{
    std::cout << "lvalue reference to const overload f(" << x << ")\n";
}

void f(int&& x)
{
    std::cout << "rvalue reference overload f(" << x << ")\n";
}

int main()
{
    int i = 1;
    const int ci = 2;
    f(i);  // calls f(int&)
    f(ci); // calls f(const int&)
    f(3);  // calls f(int&&)
           // would call f(const int&) if f(int&&) overload wasn't provided
    f(std::move(i)); // calls f(int&&)
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved