32

I have such problem: I have class Foo, and if have some objects of this class,

Foo a();

I need to put this object to 2 different vectors:

std::vector<Foo> vA, vB;

and if a changes in vA it should be changed in vB, vectors vA and vB can be different, but they can have same objects. I know that it is possible to do with Boost, but I can't use Boost.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Mike Minaev
  • 1,912
  • 4
  • 23
  • 33

3 Answers3

66

There are some possibilities:

  1. Store a vector of pointers (use if your vectors share ownership of the pointers):

    std::vector<std::shared_ptr<Foo>> vA, vB;
    
  2. Store a vector of wrapped references (use if the vectors do not share ownership of the pointers, and you know the object referenced are valid past the lifetime of the vectors):

    std::vector<std::reference_wrapper<Foo>> vA, vB;
    
  3. Store a vector of raw pointers (use if your vectors do not share ownership of the pointers, and/or the pointers stored may change depending on other factors):

    std::vector<Foo*> vA, vB;
    

    This is common for observation, keeping track of allocations, etc. The usual caveats for raw pointers apply: Do not use the pointers to access the objects after the end of their life time.

  4. Store a vector of std::unique_ptr that wrap the objects (use if your vectors want to handover the ownership of the pointers in which case the lifetime of the referenced objects are governed by the rules of std::unique_ptr class):

    std::vector<std::unique_ptr<Foo>> vA, vB;
    
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
utnapistim
  • 26,809
  • 3
  • 46
  • 82
  • 2
    If you make both vectors `std::vector>` and insert the same object in both of them, won't it result in double free? – Андрей Беньковский Oct 29 '15 at 14:42
  • 2
    @АндрейБеньковский, yes it would, because adding the same address to two distinct unique_ptr instances, is always an invalid use case (this is why unique_ptr allows move-assignment and move-construction, but neither copy-assignment nor copy-construction). – utnapistim Oct 30 '15 at 08:21
15

You need a vector of references. And since you specify that you need to use std::vector, then the correct thing to do is wrap your objects in the std::reference_wrapper. This page from C++ reference should explain it nicely:

vector<reference_wrapper<Foo>> vA, vB;
vA.push_back(a);
vB.push_back(a);    // puts 'a' into both vectors

// make changes to 'a'
// use .get() to get the referenced object in the elements of your vector
// vA[0].get() == vB[0].get()
alpartis
  • 1,086
  • 14
  • 29
  • This makes it impossible (I think) to change any of the pointers (which is either a feature or a defect, depending on what you are doing with the `vector`). – James Kanze May 06 '14 at 09:24
  • 1
    The only requirement from the OP is to store references to the Foo object, so there's no pointers here to be able to change. The programmer is free to change the contents of either vector and any of the attributes of the variable 'a' at any time. The reference itself is, by definition, immutable. – alpartis May 06 '14 at 13:45
  • It should also be mentioned that `reference_wrapper` implicitly converts to `T&`, thus making it less painful to pass around or iterate 'as-if' it is a `T&`, albeit defeating `auto` in lambda argument lists, as that mandates what I'll call a 'deliberate implicit' conversion. @JamesKanze `reference_wrapper` rebinds on assignment, rather than assigning to the referenced value, so they can be changed just as pointers could (well, not so easily as you can't do arithmetic on them, but that's *good*). – underscore_d Sep 24 '18 at 17:45
2

Instead of keeping Foo as object keep as pointer to object Foo, e.g.

std::vector<Foo *> vA, vB;

and manage allocations and deallocations carefully to avoid memory leakage (Allocating but not deallocating when done). If you allocate one Foo object and keep the pointer in both vA and vB , then you are keeping essentially same object in both through the pointer. Otherwise you may use smart pointer (better) refer:

What is a smart pointer and when should I use one?

Community
  • 1
  • 1
Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • I'm guessing people are downvoting because there are options that don't require manually (mis-)managing those pointers (smart pointers like `shared_prt`) which would be more appropriate. – Mat May 06 '14 at 07:25
  • @Mat: Especially the word *carefully* knowing we all have a bad day or two. – Benjamin Bannier May 06 '14 at 07:26
  • you are right, there are two options, use a managed pointer or manage your own pointer depending on the expertise. – Dr. Debasish Jana May 06 '14 at 07:27
  • It's nothing to do with expertise - unless you genuinely want "borrowed ownership" semantics vector of pointers is wrong. – Flexo May 06 '14 at 07:29
  • 2
    Re smart pointers: judging from the little code in his example, he probably expects the actual object to be allocated on the stack or statically. Which means no smart pointers. – James Kanze May 06 '14 at 08:47
  • One object cannot reside in both places, unless a copy is made and copy kept in second vector, but that's ruled out, as copy is not the original anyway, so changing copy does not change original. You may store reference object however, e.g. Foo orig;Foo& another = orig; and vA.push-back(orig); vB.push_back(another), but what's the point? – Dr. Debasish Jana May 06 '14 at 09:07
  • @Dr.DebasishJana No, references cannot be stored in containers... What you wrote would create 2 separate copies of the original `Foo`, and none of the 3 would change in synchrony, which blatantly contradicts what the OP requested. – underscore_d Sep 24 '18 at 17:47