std::vector when some members of Foo are refe

2020-07-10 11:01发布

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.

3条回答
我命由我不由天
2楼-- · 2020-07-10 11:20

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.

查看更多
Fickle 薄情
3楼-- · 2020-07-10 11:25

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

查看更多
Explosion°爆炸
4楼-- · 2020-07-10 11:25

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.

查看更多
登录 后发表回答