2010-09-27 3 views
0

Мне нужно хранить ссылки на экземпляры производных классов в C++. Я рассмотрел использование вектора shared_ptrs для базового класса (поскольку для его хранения требуются разные типы производных классов), однако важно, чтобы контейнер содержал исходные указатели, что не относится к векторам (или другим контейнерам stl), если я не ошибаюсь. Есть ли способ сделать это на родном C++, или мне нужно использовать специальные контейнеры, такие как post_vector Boost?C++: Контейнер исходных указателей

EDIT: Это мой тестовый код:

class Foo 
{ 
public: 
    Foo() {} 
    virtual ~Foo() {} 
    virtual void set_x(int i) = 0; 
}; 

class Bar : public Foo 
{ 
public: 
    Bar() {} 

    void set_x(int i) 
    { 
     this->x = i; 
    } 

    int x; 
}; 

int main() 
{ 
    Bar bar; 

    // ptr 
    std::cout << &bar << "\n"; 

    std::vector<Foo*> foos; 
    foos.push_back(&bar); 

    // different ptr value 
    std::cout << &foos[0] << "\n"; 

    foos[0]->set_x(1); 

    // however, changes are made 
    std::cout << bar.x; 

    return 0; 
} 

Спасибо заранее,

Jena

+0

Будет ли вектор (вектор указателей на ваши объекты) не подходит для вас? – JoshD

+0

Мне непонятно, почему контейнер 'shared_ptr' не будет работать для вас. –

+0

Я пробовал это, но когда я добавляю указатель экземпляра через vector.push_back (& ​​instance), указатель в векторе отличается от исходного. – jena

ответ

1

В приведенном выше примере то, что вы печатаете, является адресом указателя, а не значением указателя.

Вместо:

// different ptr value 
std::cout << &foos[0] << "\n"; 

ли

// different ptr value 
std::cout << foos[0] << "\n"; 

Помимо этого ваш vector<Foo*> будет работать нормально.

+0

Это удручает ... Вы правы, конечно. Спасибо, что указали, что я должен действительно поспать. Спасибо всем за вашу помощь. Прошу прощения за эту пустоту. – jena

+0

Я рад, что смогу помочь. Если бы это было хорошее решение, не могли бы вы отметить его как принятый ответ? – JoshD

0

Если вы используете shared_ptr в качестве элемента контейнера, указателя в каждом элементе сохранит доступ к исходный экземпляр объекта. Вы можете получить копию shared_ptr в любой момент после уборки контейнеров, но исходный объект по-прежнему будет его целью.

Для более простого решения вы можете использовать boost::ptr_vector, при условии, что ни один из ваших указателей не появится дважды в контейнере - этот сценарий вызовет сложную сложность управления ресурсами и вернет вас к shared_ptr.

+0

Понял ли shared_ptr типы, которые не выделены в куче? – jena

+0

Nope. В этом случае, когда переменная выходит за пределы области видимости, ваш 'shared_ptr' будет указывать на мусор в стеке, а может быть даже недоступную память, после того, как стековый фрейм разматывается. –

1

Вы можете создать std :: vector < foo *>, который будет содержать любые указатели на foo, которые вы ему передадите. Это не будет предпринимать попытки удалить эти указатели при уничтожении, что может быть или не быть тем, что вы хотите, но оно будет содержать точно значения, которые вы передаете.

Вы также можете создать std :: vector < shared_ptr < foo>>, в котором будут удерживаться указатели, которые будут выпущены, когда нет оборванных копий shared_ptr, плавающих вокруг. Они также проведут «оригинальный» foo *, который вы прошли; вы можете получить его снова, используя метод shared_ptr :: get().

Единственный раз, когда вы не видите точно такой же указатель, что и ваш производный объект, если вы используете множественное наследование классов, а ваши базовые классы включают данные. Поскольку foo * закончится, в этом случае, указывая на «foo» часть данных, которая не обязательно будет находиться в «корне» объекта.

+0

Я не использую множественное наследование, но базовый класс содержит данные. Может ли это быть причиной того, что элементы в векторе имеют разные указатели от оригиналов? – jena

+0

Не видел ваш пример в первый раз; другой ответ уже попал в мясо вашей проблемы, а именно, что вы получали адрес данных VECTOR, а не сам указатель. Сон является важной частью развития. :) – SomeCallMeTim

Смежные вопросы