简体   繁体   中英

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

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.

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 like std::vector<std::reference_wrapper<int>> v

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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM