C — Объект, уничтоженный вне области видимости и в векторе

#c #arrays #vector

#c #массивы #вектор

Вопрос:

Почему вызывается деструктор объекта, когда он выходит за пределы области видимости и когда он находится в векторе? Например :

 std::vector<Foo> vec;
for (i=10; i<10; i  )
{
   Foo object(i);
   vec.push_back(object);
} 
  

Вызывается ли деструктор объекта, потому что он каждый раз выходит за пределы области видимости? Могу ли я заставить его работать без указателей или shared_pointers?

Комментарии:

1. Да; используйте emplace_back и создавайте Foo на месте.

2. То, что заканчивается в векторе, является копией object , а не object самим собой. object уничтожается при выходе из области видимости; его копия продолжает жить внутри вектора. Из вашего вопроса неясно, почему вы считаете это проблемой. Какую актуальную проблему, если таковая имеется, вы пытаетесь решить?

3. Я был сбит с толку и подумал, что вектор принял указатель на объект, поскольку функция push_back принимает объект по ссылке. Спасибо.

4. Ссылка не является указателем (если мы не говорим о том, как компиляторы реализуют ссылки, но это не так). Ссылка — это, по сути, другое имя для объекта, на который ссылается объект, и часто используется при передаче объектов. Поскольку ваш вектор хранит Foo , а не Fooamp; нет, он будет использовать эту ссылку для копирования, создает свою собственную object , после чего ссылается на то, что сказал @Igor выше.

5. Спасибо. Хотя я знаю, что ссылка не является указателем и что нельзя создавать массивы или ссылки.

Ответ №1:

  • push_back помещает копию объекта в вектор
  • объект фактически будет уничтожен, но копия сохранится в векторе
  • Если вы хотите поместить точное содержимое объекта в вектор и заставить код работать, тогда используйте конструктор перемещения

Комментарии:

1. Итак, если я использую конструктор перемещения, объект не разрушается?

2. он будет уничтожен, но его содержимое будет перенесено в вектор, копирование выполнено не будет. это более эффективно

3. Хорошо, проблема в том, что в моем деструкторе объектов он уничтожает элементы в других объектах, поэтому я не хочу, чтобы он уничтожал эти элементы.

4. Мне уже некоторое время не нужно было использовать деструктор в таких случаях. Что это за элементы? Динамическое распределение? Затем попробуйте удалить его и использовать shared_ptr .

5. Я не видел весь ваш код. попробуйте переместить и скажите мне. Он сохраняет содержимое объекта. Если нет, вам нужно прислать мне еще немного кода или отредактировать его.

Ответ №2:

object исчезнет за пределами этой области видимости, это правильно. Нет, vector не влияет и не мог повлиять на его время жизни. push_back фактически копирует object в vector . Чтобы избежать этого, вы можете использовать C 11, emplace_back который позволяет создавать Foo на месте:

 vec.emplace_back(i);
  

Эта тестовая программа подтверждает, что копирование, перемещение или дополнительное уничтожение не выполняется.

 Constructing A
End of vec's scope
Destructing A
  

Комментарии:

1. Это все равно создает временный объект Foo , затем копирует его в вектор, а затем сразу уничтожает. Конечный результат точно такой же, как в исходном коде (за исключением того, что он использует конструктор по умолчанию Foo , тогда как в оригинале используется конструктор, принимающий int ). Вы, вероятно, имели в виду vec.emplace_back(i); или vec.emplace_back(); — это создает один-единственный экземпляр Foo на месте (с использованием однопараметрического конструктора или конструктора по умолчанию, соответственно).

2. Правильно, я запутался. Я понял это позже, когда экспериментировал с Coliru. push_back и emplace_back в этом случае не сильно отличаются : coliru.stacked-crooked.com/a/b2894b7f4b2a8367

3. Опять же — чтобы увидеть разницу, сделайте это vec.emplace_back()

4. Я думаю, что ваш ответ подходит мне лучше всего, потому что деструктор моего объекта является дорогостоящим, поэтому лучше создать только один объект.

5. о, я пропустил суть и не знал, как должен был использоваться emplace_back. я отредактирую свой ответ соответственно этому. Спасибо!

Ответ №3:

Это должно сработать

 std::vector<Foo> vec;
for (i=10; i<10; i  )
{
   vec.emplace_back(i);
} 
  

Комментарии:

1. вы должны удалить foo object(i);

2. Это следует удалить