std::vector<Foo> when some members of Foo are references

陌路散爱 提交于 2019-12-06 00:34:15

问题


I often prefer to use references than pointers whenever possible, it makes the syntax cleaner in my opinion. In this case, I have a class:

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

private:
    Bar & bar_;
};

operator=() is implicitely deleted by the compiler for such a class, since once a reference is set, it cannot be changed (I can technically define my own that doesn't change bar_, but this would not be the required behaviour, so I'd rather the compiler complain if I try to assign a foo).

What I need is a std::vector<Foo> v;. This is impossible before C++11, since the template parameter must to be CopyAssignable. Indeed, when I call v.push_back(Foo(bar));, the compiler complains. But I feel it could be possible since C++11 and Move semantics.

My question is: is there a workaround using C++11 that would make building such a vector possible, or am I stuck in this case and have no way around using pointers instead of references? If there's a workaround, I'd highly appreciate a code snippet since I'm unfamiliar with move semantics.


回答1:


Voila emplace_back is able to do the job because of perfect forwarding.

#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);                                                     
} 

You can also store a reference by itself in a container with std::reference_wrapper used likestd::vector<std::reference_wrapper<int>> v




回答2:


Use v.emplace_back(bar) instead of push_back. It will construct a Foo in place in the memory vector has allocated for it, thus requiring no copying. Just pass emplace_back the arguments to construct a Foo.




回答3:


The template parameter of a container doens't have to be CopyAssignable, it depends on what operations you perform on your container, and if you really use operation that requires CopyAssignable or MoveAssignable, you cannot use a reference as you wish (even with move semantic). But if you use only other operations (see standard), it will be fine. Some operations only needed CopyInsertable, MoveInstable and/or EmplaceConstructible.



来源:https://stackoverflow.com/questions/19801932/stdvectorfoo-when-some-members-of-foo-are-references

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!