2016-05-13 53 views
0

讓我有一個自定義的包裝容器。我想這樣使用它:如何將右值生命週期擴展到我的自定義容器生命週期?

double d = 3.14; 
MyContainer<std::vector<int>> pointer = new std::vector<int>(); 
MyContainer<std::string> rvalue = std::string("foo"); 
MyContainer<int> rvalue2 = 5 + 8; 
MyContainer<double> lvalue = d; 

我不想存儲rvalues的副本(引用是好的)。 Rvalue參考允許我這樣做:

std::string string1 = "foo"; 
std::string string2 = "bar"; 
std::string&& string3 = string1 + string2; 
string3 += "test"; 

基本上我想延長rvalues的生命期到我的容器的一生。然而,當我這樣做:

template<class T> 
class MyContainer { 
public: 
    MyContainer(T&& obj) : object(obj) {} 
    T&& object 
    ... 
}; 
... 
MyContaier<std::string> container = MyContainer(std::string("foo")); 

我得到一個錯誤(不能綁定 '的std :: string' 左值到 '的std :: string & &')。這個例子稍有不同,但我只想了解一個大概的想法。我怎樣才能避免這種情況?

+0

你的意思是'T &&對象;'在MyContainer'中,而容器實際上是一個「容器引用」?如果是這樣,那麼你的'std :: vector'例子將無法編譯,並且這與你的其他案例有不同的語義(你在這種情況下使用了動態分配) –

+0

'object(obj)'應該是'object(std :: move(obj))',這可能是你的編譯器錯誤,但它不能解決生命期問題(你現在有沉默的未定義行爲) –

+0

延長工作時間的唯一方法是如果MyContainer是一個集合,使用聚合初始化,[見這裏](http://stackoverflow.com/questions/23892018/extending-temporarys-lifetime-through-rvalue-data-member-works-with-aggregate)。即在這種情況下,你不能有任何用戶定義的構造函數。否則,你只需要給它賦值語義。 –

回答

0

除了您的代碼有多個拼寫錯誤和語法錯誤,沒有任何技術上阻止您採用std::string的右值引用(儘管您的賦值/構造函數調用不正確)。將T & &作爲成員變量不會像您認爲的那樣工作。只要到達下一個序列點,存儲對過期右值的引用,然後訪問它即可。

下面是一個有關右值引用和左值引用的構造函數的工作示例。如果你想「擁有」它,你需要在你的對象內部有一個實際的實例。你無法在技術上延長即將到期的右值的生命週期;你只能構建其他重用它的東西(並希望竊取一些昂貴的內臟)。希望這可以幫助。

#include <utility> 
#include <string> 
#include <iostream> 

template<class T> 
class MyContainer { 
public: 

    // makes a copy from an lvalue reference 
    MyContainer(const T& obj) 
     : object(obj) { 
    } 

    // moves from an rvalue reference 
    MyContainer(T&& obj) 
     : object(std::move(obj)) { 
    } 

    MyContainer& operator=(const T& obj) { 
     object = obj; 
    } 

    MyContainer& operator=(T&& obj) { 
     object = std::move(obj); 
    } 

    T object; 
}; 

int main() { 

    MyContainer<std::string> container = std::string("foo"); 
    std::cout << container.object; 
} 
+0

Downvote?這段代碼是完全正確的,並回答了這個問題。 –

+0

我應該提供有關容器的更多信息。我希望它是一個聰明的指針。所以技術上可以有多個拷貝綁定到同一個對象。這就是爲什麼我不想保留一個對象的副本。右值引用可以有效地延長生命期,但看起來像我必須在這裏使用聚合初始化。 –

+0

查看已更新的答案。 –