В чем разница между этими использованиями: новый SubElement () и SubElement ()? - PullRequest
3 голосов
/ 02 апреля 2010

В конструктор класса мне нужно на лету создать несколько объектов и добавить их в вектор. Вот мой код:

ContainerClass::ContainerClass() {
   for (int i = 0; i < limit; i++)
      elements.push_back(SubElement());
}

Это то же самое с новым SubElement ()? Нужно ли мне освобождать эти объекты SubElement () в деструкторе ContainerClass?

Ответы [ 4 ]

6 голосов
/ 02 апреля 2010

Метод 1:

Если у вас есть std::vector<SubElement> elements;
Тогда вы будете использовать elements.push_back(SubElement()).

SubElement() создает SubElement в стеке, а затем копия добавляется в vector.

Вы НЕ должны вызывать delete для отдельных элементов vector. Они будут уничтожены и освобождены, когда vector выйдет за рамки.

Метод 2:

Если у вас есть std::vector<SubElement*> elements;
Тогда вы будете использовать elements.push_back(new SubElement()).

new SubElement() создает SubElement в куче, а затем адрес этого элемента сохраняется в vector.

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

1 голос
/ 02 апреля 2010

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

C ++ - один из немногих объектно-ориентированных языков, где вы можете ссылаться на объект по значению.

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

Часто копии на основе стека будут упоминаться ссылкой (вся идея & обозначена как спецификатор типа), но обычно считается, что эти ссылки недолговечны, и обычно делается копия того объекта, на который делается ссылка если эту вещь нужно хранить некоторое время.

В частности, в этом случае, если у вас есть контейнер указателей (т.е. ::std::vector<SubElement *> c), он хранит указатели на объекты, и вы обычно выделяете их с помощью new. Но стандартные контейнерные классы библиотеки (и большинство других контейнерных классов) не удаляют указатели для вас. Они не берут «владение» указателем. Таким образом, вы сами будете отвечать за их удаление.

Если у вас есть контейнер объектов (например, ::std::vector<SubElement> c), вы должны использовать форму c.push_back(SubElement()), и в этом контейнере будут храниться копии созданных вами временных файлов. Контейнер становится владельцем этих копий, а также часто копирует их изнутри. Вот почему объекты, которые вы храните по значению в контейнере, должны реализовывать конструктор копирования.

Есть способ заставить контейнер получить владение указателями, но только косвенно. В контейнере можно хранить копии объектов, которые сами становятся собственниками. Для этого используют стандартный класс ::std::tr1::shared_ptr<T>. Ваша декларация контейнера будет выглядеть так: ::std::vector< ::std::tr1::shared_ptr<SubElement> > c. Затем вы можете сделать: c.push_back(new SubElement()); и контейнер удалит объекты SubElement, когда это будет сделано.

Вы должны прочитать shared_ptr и по-настоящему понять, что он делает, прежде чем использовать его.

1 голос
/ 02 апреля 2010

Нет - они разные.

Just SubElement() создает автоматический (стек) объект, который должен быть скопирован для сохранения.

new SubElement() создает динамически размещаемый объект в куче, и его следует назначить указателю на такой объект. Это должно быть выпущено в конце концов, чтобы предотвратить утечку памяти.

1 голос
/ 02 апреля 2010

SubElement (): автоматически назначается, новый SubElement (): динамически назначается.

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

...