std :: vector <foo>当Foo的某些成员是引用</foo>时

时间:2013-11-06 00:39:48

标签: c++ c++11 stdvector move-semantics

我经常喜欢尽可能使用引用而不是指针,这使我的语法清晰。在这种情况下,我有一个班级:

class Foo
{
public:
    Foo(Bar & bar) : bar_(bar) {}

private:
    Bar & bar_;
};
编译器为这样的类隐含地删除了

operator=(),因为一旦设置了引用,它就无法更改(我可以在技术上定义我自己的不会改变bar_,但这不是所需的行为,所以如果我尝试分配一个foo,我宁愿编译器抱怨。

我需要的是std::vector<Foo> v;。这在C ++ 11之前是不可能的,因为模板参数必须是CopyAssignable。实际上,当我调用v.push_back(Foo(bar));时,编译器会抱怨。但我觉得自从C ++ 11和Move语义以后就可以了。

我的问题是:是否有使用C ++ 11的解决方法可以使构建这样的向量成为可能,或者我是否陷入这种情况并且无法使用指针而不是引用?如果有一个解决方法,我非常感谢代码片段,因为我不熟悉移动语义。

3 个答案:

答案 0 :(得分:6)

Voila emplace_back因完美转发而能够胜任。

#include <vector>                                                                  

class Bar{};                                                                       
class Foo                                                                          
{                                                                                  
public:                                                                            
    Foo(Bar & bar) : bar_(bar) {}                                                  

private:                                                                           
    Bar & bar_;                                                                    
};                                                                                 
using namespace std;                                                               
int main() {                                                                       
    vector<Foo> v;                                                                 
    Bar bar;
    v.emplace_back(bar);                                                     
} 

您还可以将引用自身存储在std::reference_wrapper使用的容器中,例如std::vector<std::reference_wrapper<int>> v

答案 1 :(得分:1)

使用v.emplace_back(bar)代替push_back。它将在为Foo分配的内存中构造一个vector,因此不需要复制。只需传递emplace_back参数即可构建Foo

答案 2 :(得分:0)

容器的模板参数不必是CopyAssignable,它取决于您对容器执行的操作,如果您真的使用需要CopyAssignable或MoveAssignable的操作,则不能使用您想要的引用(甚至用移动语义)。但是如果你只使用其他操作(参见标准),那就没问题了。某些操作只需要CopyInsertable,MoveInstable和/或EmplaceConstructible。