简体   繁体   中英

Creating an array of objects containing references

What is the best way to deal with the following situation?

Suppose that I have something that should behave like this

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

Foo:s must have a valid reference to Bar:s. Also different Foo:s needs different or the same Bar:s.

I want to store Foo:s in an array. However, since Foo will require a non-default constructor, it will not work.

I could create an array of pointers to Foo:s, but then I need to call new and delete for each object in that array.

I could define Foo like this instead

class Foo
    {
    public:
         void init(Bar& bar)
             {
             m_bar=&bar;
             }
    private:
         Bar* m_bar;
    };

, but then it is possible to create uninitialized Foo:s.

What about some sort of placement new?

You could use pointers still but instead of using raw pointers use unique_ptrs. These are available in c++11, but if you are using an older compiler you could use the boost implementation.

For example

class Foo
{
public:
  Foo(unique_ptr<Bar> bar):m_pBar(bar){}
private:
  unique_ptr<Bar> m_pBar;
};

This way you don't have to worry about calling delete on your Bar objects as they are deleted once there are no more references to them.

Then you can use Foo like this

unique_ptr<Bar> pBar(new Bar());
Foo(pBar);

EDIT: Changed to use unique_ptr instead of shared_ptr and added example usage

First, sorry for my first answer I got the question wrong. Here is a better solution I hope: you can create a vector of elements without default constructor like this:

#include <iostream>
#include <vector>

using namespace std;


class Foo 
{ 
public: 
    Foo(int& bar): m_pBar(bar)
    { } 

    Foo& operator=(const Foo& other)
    { m_pBar = other.m_pBar;  }

    int Get()
    { return m_pBar; }

private: 
    int& m_pBar; 
}; 


int main(int argc, char** argv)
{
    int test[10]  = { 0 };

    vector<Foo> vect;
    for (int& i: test)
        vect.emplace_back(i);

    test[0] = 1;
    cout << vect[0].Get() << endl;

    return 0;
}

Finally I implemented a custom container with the following constructor:

template<class T>
template<class U,class V>
Array<T>::Array(unsigned int n,U source_iterator,const V& source_resource):memory(n*sizeof(T))
    {
    data=(T*)memory.pointerGet();
    unsigned int k;
    try
        {
        for(k=0;k<n;k++)
            {
            new(data+k)T(*source_iterator,source_resource);
            ++source_iterator;
            }
        }
    catch(...)
        {
        while(k>0)
             {
             k--;
             data[k].~T();
             }
        throw;
        }
    length=n;
    capacity=n;
}

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