C++11函數返回右值引用


我們定義了一個可以傳入右值引用的構造函數的類B,在使用std::move的時候,我們非常容易犯一個錯誤。看下面的代碼:

 

class B
{
public:
    B() :s(10), ptr(new int[s])
    {
       std::cout << "default constructor" << std::endl;
       for (int i = 0; i < s; i++)
       {
          ptr[i] = i;
       }
    }
    B(const B& b) :s(b.s)
    {
       std::cout << "B&b" << std::endl;
       for (int i = 0; i < s; i++)
          ptr[i] = b.ptr[i];
    }
    B(B&& b) :s(b.s), ptr(b.ptr)
    {
       std::cout << "B&& b" << std::endl;
       b.ptr = 0;
    }
    ~B()
    {
       std::cout << "~B()" << std::endl;
       if (ptr)
          delete[] ptr;
    }
    friend  std::ostream& operator <<(std::ostream& os, B& b);
private:
    int s;
    int* ptr;
};
std::ostream& operator <<(std::ostream& os,B& b)
{
    os << "[ ";
    for (int i = 0; i < b.s; i++)
       os << b.ptr[i] << " ";
    os << "]" << std::endl;
    return os;
}

B&& f()//注意這里B&&
{
    B tmp;
    return std::move(tmp);
}



B& f2()//注意這里的B&
{
    B t;
    return t;
}
int main()
{
 B b0(f2());
 B b1(f()):
return 0 ;
}

  函數f2返回B的引用,但是B是一個臨時對象,馬上就會被析構,b0的構造函數傳入的參數是一個已經被析構的對象!大家能夠非常容易就看出錯誤所在。

但是,函數f返回std::move(tmp),不容易發現問題。

展開函數f():

首先一個B的臨時對象tmp被創建,使用std::move(tmp),將tmp由左值變為右值的引用,它是右值。編譯創建一個臨時對象B&& _tmp = std::move(tmp)。_tmp被傳遞給對象b1的構造函數。

無論是右值引用還是左值引用,它們都是引用。所以,f()和f2()發生了同樣的錯誤!

我們可以這樣修改:

B f()
{
    B tmp;
    return std::move(tmp);
}

展開函數f():

首先一個B的臨時對象tmp被創建,使用std::move(tmp),將tmp由左值變為右值的引用,它是右值。編譯創建一個臨時對象B _tmp = std::move(tmp)。_tmp調用構造函數B(B&&),轉移tmp的空間和大小。_tmp被傳遞給對象b1的構造函數。

以上。

再附上幾個容易混淆的代碼:

int& f1(int& a)
{
    return a;
}//正確,返回a的引用

int main()
{
 int&& i = 123;
 int&& a = i;//錯誤,不能將左值賦給右值引用。如果你犯了這個錯誤,請務必思考清楚:引用對象在完成初始化后,這個對象的類型是什么。提示,i是一個具名引用。
 int&& b = std::move(i);//正確
 return 0;
}

 


 

重新看了一遍C++11的書,關於引用類型感覺收獲了很多。

1.因為我們使用引用類型的變量,就跟使用所引用類型的變量一樣,導致我忘了引用類型是一種類型。比如:

int  a = 1;
int& b = a;
int& c = b;
b = c;

自從b被初始化后,用起來它就是一個int的變量一樣。實際上,它確實一個int的引用類型,而不是int。

2.關於C++11中模板的參數類型推斷,有兩個特殊情況。

template<typename T> void function(T&& a);

如果傳給function的實參是一個左值,則T被推斷為T&,而不是T。這是第一個特殊情況。

如果T& && 被折疊為T&,這是第二個特殊情況。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM