2012-02-29 6 views
0

Каков наилучший способ справиться со следующей ситуацией?Создание массива объектов, содержащих ссылки

Предположит, что у меня есть то, что должно вести себя как этого

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

Foo: s должен иметь действительную ссылку Bar: с. Также разные Foo: s нужны разные или одинаковые Bar: s.

Я хочу хранить Foo: s в массиве. Однако, поскольку Foo потребует конструктор, отличный от стандартного, он не будет работать.

Я мог бы создать массив указателей на Foo: s, но тогда мне нужно вызвать new и delete для каждого объекта в этом массиве.

Я мог бы определить Foo, как это вместо

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

, но тогда можно создать неинициализированный Foo: с.

Что относительно какого-то размещения нового?

ответ

0

Во-первых, извините за мой первый ответ, который я получил вопрос неправильно. Вот лучшее решение, которое я надеюсь, что вы можете создать vector элементов без конструкторы по умолчанию, как это:

#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; 
} 
+0

Но если Foo также содержит BLOb, который я не хочу копировать? – user877329

+0

Я не уверен, где вы видите копирование здесь. * Будьте осторожны с ожидаемой оптимизацией *. Во-первых, «копия», вероятно, будет оптимизирована компилятором в «перемещении», во-вторых, это, вероятно, не так медленно, в-третьих, вы также можете использовать ссылку для Blob ... –

+0

Ну, оператор присваивания копирует данные из другого источника 'В' * это '. Когда я говорю BLOb, я имею в виду что-то, что может быть несколько меганов. – user877329

0

Вы можете использовать указатели, но вместо использования raw-указателей используйте unique_ptrs. Они доступны в C++ 11, но если вы используете старый компилятор, вы можете использовать реализацию boost.

Например

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

Таким образом, вам не придется беспокоиться о вызове удаления ваших объектов Bar, как они будут удалены раз больше нет ссылок на них.

Затем вы можете использовать Foo как этот

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

EDIT: Изменены использовать unique_ptr вместо shared_ptr и добавил пример использования

+0

Я думаю, что 'unique_ptr 'было бы предпочтительнее. Нет необходимости делиться данными между многими потоками. –

+0

согласился. Я изменю свой ответ, чтобы отразить это. –

+0

все еще вызывает новый вызов для каждого объекта, не так ли? – user877329

0

Наконец я реализовал пользовательский контейнер со следующим конструктору:

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; 
} 
Смежные вопросы