std :: vector, конструкторы, объекты - PullRequest
1 голос
/ 04 февраля 2011

следующий конструктор

 std::vector<Object> objects(n);

создает n объектов, вызывающих конструктор по умолчанию, то есть что-то вроде этого:

std::vector <Object> objects;
for (unsigned int i = 0; i < n; i++) objects.push_back(o);

Является ли эта процедура действительной и для динамически размещаемых объектов? Есть ли конструкция

std::vector<Object *> objects(n);

представляют эту функциональность?

std::vector <Object*> objects;
for (unsigned int i = 0; i < n; i++) objects.push_back(new Object());

Если нет, есть ли способ как это устроить?

Ответы [ 4 ]

6 голосов
/ 04 февраля 2011
std::vector<Object> objects(n); 

Поведение этого зависит от того, какую версию C ++ Standard реализует ваша реализация Стандартной библиотеки:

  • В C ++ 03 это создает одну конструкцию по умолчанию Object, а затем копирует конструкции для этого объекта n раз.

  • В C ++ 0x эта конструкция по умолчанию n Object s.

Разница обычно не имеет значения, но это хорошо знать.


std::vector<Object *> objects(n);  

Это создает vector с n null Object* s. Поскольку Object* не является типом класса и не имеет конструктора, вновь вставленные объекты инициализируются значением, что для указателей означает, что они установлены в NULL.

Если вы хотите динамически создавать новые объекты и затем хранить указатели на них в контейнере, вам нужно вызвать new самостоятельно. Обратите внимание, что вы не должны хранить необработанные указатели в стандартном контейнере библиотеки, если контейнер владеет указанными объектами. Это не исключение безопасно.

Вместо этого следует использовать интеллектуальный указатель, например shared_ptr или unique_ptr (примечание: интеллектуальный указатель auto_ptr не может храниться в контейнерах из-за его необычной семантики копирования, поэтому shared_ptr или unique_ptr б).

В любом случае, чтобы вставить указатели на n различных динамически размещаемых объектов в контейнер, вам нужно вызвать new n раз, чтобы создать эти n объектов. Нет ничего плохого в вашем for петлевом решении.

2 голосов
/ 04 февраля 2011

следующий конструктор

std::vector<Object> objects(n);

создает n объектов, вызывающих конструктор по умолчанию

Да, но конструктор по умолчанию используется только для создания второго необязательного параметра для конструктора vector, объекты n в векторе создаются путем копирования этого параметра. [Ответ C ++ 03]

Если вы сделали что-то вроде:

std::vector<Object*> objects(n, new Object());

вы бы динамически распределяли один объект и имели n указатели на этот объект в вашем vector, что, вероятно, не то, что вы хотите.

Почти всегда плохая идея использовать контейнер указателей, если предполагается, что этот контейнер владеет динамически размещенными объектами. Вы должны рассмотреть что-то вроде boost::ptr_vector, или, если это невозможно, контейнер умных указателей (но не std::auto_ptr).

0 голосов
/ 04 февраля 2011

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

Вам также понадобится delete каждый из этих объектов, когда вы закончите с ними тоже.

0 голосов
/ 04 февраля 2011

Ваш последний пример кода имеет правильную общую идею, но действуйте осторожно: vector будет не управлять выделением для вас, если вы это сделаете! Например, objects.clear() приведет к утечке памяти.

Возможно, вы вместо этого захотите использовать std::vector<some_smart_ptr<Object> >, но выбор правильного класса интеллектуального указателя требует, к примеру, осторожности и внимания к тому, что происходит при копировании элементов из одного вектора в другой. boost::shared_ptr является безопасным выбором, но может иметь ненужные накладные расходы для вашего варианта использования. boost::ptr_vector может быть лучше.

...