2013-11-23 3 views
6

В моем коде на C++ у меня есть объект класса, снабженный полем id типа int. Теперь я хочу создать вектор указателей типа Object *. Сначала я попробовалСоздание вектора указателей C++

vector<Object*> v; 

for(int id=0; id<n; id++) { 
    Object ob = Object(id); 
    v.push_back(&ob); 
} 

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

vector<Object*> v; 
Object ar[n]; 

for(int i=0; i<n; i++) { 
    ar[i] = Object(i); 
} 

for(int i=0; i<n; i++) { 
    v.push_back(ar+i); 
} 

Есть еще возможность получить утечку памяти, если я сделать это таким образом? Также, по моему мнению, рассмотрение объявления массива немного неуклюжие. Существуют ли другие способы создания вектора указателей, но избегайте ручного управления памятью?

EDIT: Почему я хочу указатели вместо простых объектов?

Ну, я немного изменил исходную ситуацию, потому что я так думал, что могу представить вопрос в простейшей возможной форме. В любом случае, я все еще думаю, что на вопрос можно ответить, не зная, почему я хочу вектор указателей.

На самом деле у меня есть

Class A { 
protected: 
    vector<Superobject*> vec; 
... 
}; 

Class B: public A {...}; 

Class Superobject { 
protected: 
    int id; 
... 
} 

Class Object: public Superobject {...} 

В производном классе B Я хочу, чтобы заполнить поле члена vec с объектами типа Object. Если бы суперкласс не использовал указатели, у меня были бы проблемы с обрезкой объектов. Поэтому в классе B конструктор я хочу инициализировать vec как вектор указателей типа Object*.

EDIT2

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

В конструктор класса B Я был

B(int n) { 
    vector<Object*> vec; 
    Object ar[n]; 

    for(int id=0; id<n; id++) { 
     ar[id] = Object(id); 
    } 

    for(int id=0; id<n; id++) { 
     v.push_back(ar+id); 
    } 
} 

Это вызвало очень странное поведение в объектах класса В.

+2

Если вы не хотите динамического распределения памяти, то почему вы используете указатели? Вы можете также работать с массивом Object. –

+1

Почему вы хотите сохранить указатели в первую очередь? – Yuushi

+1

Проблема с вашим вторым методом заключается в том, что это не легальный C++. 'Object ar [n];' не является законным, если n не является константой. Кроме того, поскольку согласно вашему правлению у вас есть иерархия классов, но с 'Object ar [n];' у вас есть только объекты, а не суперобъекты. Кстати, ваш первый метод также неверен по той причине, что вы храните адреса объектов, которые были уничтожены. Я бы просто использовал динамическое распределение памяти. – john

ответ

6

В этом цикле:

for(int id=0; id<n; id++) { 
    Object ob = Object(id); 
    v.push_back(&ob); 
} 

Вы создаете п раз экземпляр объекта на стеке. На каждой итерации создается и удаляется элемент. Вы можете просто избежать этого, используя это:

for(int id=0; id<n; id++) { 
    Object* ob = new Object(id); 
    v.push_back(ob); 
} 

спасибо, что каждый новый элемент существует в куче не на стеке. Попробуйте добавить в класс объектов конструктора что-то вроде этого:

std::cout<<"Object ctor()\n"; 

и то же самое в деструкторе:

std::cout<<"Object dtor()\n"; 

Если вы не хотите создавать эти объекты с «новой» попробовать причину, написанную @ woolstar

+0

+1 за обнаружение ошибки – Pat

3

Нет нет утечки памяти в вашей версии. Когда программа оставляет область видимости, а также уничтожается массив. К вашему второму вопросу: почему бы просто не хранить объекты непосредственно в векторе?

vector<Object> v; 

for(int i = 0; i < n; i++) 
{ 
    Object obj = Object(i); 
    v.push_back(obj); 
} 
5

Ваш вопрос об утечке памяти заставляет меня думать, что вы беспокоитесь о жизненном цикле и очистке этих объектов. Первоначально я предложил shared_ptr обертки, но C++ 11 дал нам unique_ptr, а C++ 14 заполнил отсутствующий make_unique.Таким образом, со всем, что мы можем сделать:

vector<unique_ptr<SuperObject>> v ; 

Что вы создаете в месте с замечательностью совершенного экспедирования и переменных числом шаблонов,

v.push_back(make_unique<Object>(...)) ; 

Да вы собираетесь жить с некоторым распределением кучи, но все будет очищено, когда v уйдет.

Кто-то предложил библиотеку boost, ptr_container, но для этого требуется не только добавление повышения вашего проекта, но и обучение всех будущих читателей тому, что это такое ptr_container.

+3

Пожалуйста, если вам не нужна семантика shared_ptr, не делайте этого. Просто используйте http://www.boost.org/doc/libs/1_55_0/libs/ptr_container/doc/ptr_container.html. – KitsuneYMG

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