2016-05-13 29 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

查看已更新的答案。 –