вектор указателей вместо объектов

0

Каждый раз, когда вы помещаете объект в std :: vector, он должен сделать копию этого объекта.

Так что я могу просто наложить указатели вместо таких объектов?:

Class *ptr_Class;
Class object;
ptr_Class = &object;

std::vector<Class*> vector;
vector.push_back(ptr_Class);

Или по какой-то причине это не очень хорошая идея?

  • 1
    Нет проблем с указателями на векторы. Это довольно часто. Единственное, в чем вы должны убедиться, это то, что объекты правильно очищаются после использования. Т.е. когда вектор выходит из области видимости и вызывается его деструктор, он не будет удалять / освобождать объекты (в отличие от помещения копий в вектор, что и происходит).
  • 1
    Проблемы с копированием гораздо меньше, чем в C ++ 11.
Показать ещё 4 комментария
Теги:
pointers
vector

3 ответа

3

Используйте вектор интеллектуальных указателей. таким образом, вы не получите утечек памяти.

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

1

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

Безопаснее использовать вектор интеллектуальных указателей, который автоматически позаботится об этой очистке, даже перед исключениями. В С++ 11 вы можете просто создать вектор std::unique_ptr<T>. С более старыми компиляторами, которые не поддерживают С++ 11, вы можете использовать std::tr1::shared_ptr<T> или boost::shared_ptr<T>, хотя это имеет некоторые накладные расходы из подсчета ссылок, которые вы не используете очень нужно. Вы не можете поместить С++ 98 std::auto_ptr в вектор (поэтому он устарел и заменен на std::unique_ptr в С++ 11).

Кроме того, в С++ 11 у вас есть некоторые опции для избежания копирования при вставке объекта в вектор:

  • Вы можете вызвать myvector.push_back(std::move(myobject)) чтобы переместить объект в вектор, а не копировать его. Это все еще создает новый экземпляр внутри вектора, но он позволяет владеть любыми ресурсами, myobject вместо их копирования. После этого myobject не следует использовать, поскольку он больше не содержит данные, к которым он привык.
  • Вы можете вызвать myvector.emplace_back(...) для создания нового объекта непосредственно в хранилище векторов. Это в основном оболочка для вашего конструктора классов, и ему может быть предоставлен любой набор аргументов, которые являются действительными для перехода к этому конструктору.

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

  • 0
    Вектор указателей - не единственный вариант хранения полиморфных объектов. Как показал Шон Родитель, вы можете сделать полиморфизм деталью реализации. Магия внизу.
  • 0
    @ Крис, интересная идея там - в основном способ реализовать «интерфейс» со свободными функциями вместо необходимости писать производный класс вручную. Но в основе он все еще работает, удерживая указатель на абстрактный базовый класс: concept_t в видео, DrawableConcept в другой вашей ссылке. Все остальное - просто представить клиенту более приятный API.
Показать ещё 1 комментарий
1

Вы не используете "новое" или выделяете память, поэтому технически вы не будете иметь утечек памяти.

Однако вы должны быть осторожны с областью. Например, если у вас есть

std::vector<Class*> funcFoo()
{
    Class *ptr_Class;
    Class object;
    ptr_Class = &object;
    std::vector<Class*> vector;
    vector.push_back(ptr_Class);
    return vector;
}

вы получите вектор указателя, указывающего на объект в funcFoo. Этот объект, скорее всего, будет мусором после того, как вы покинете эту функцию.

Я предполагаю, что то, что вы хотите, больше похоже на это:

Class *ptr_Class = new Class();
std::vector<Class*> vector;
vector.push_back(ptr_Class);

Если это так, то вы должны помнить, чтобы освободить любую память, вы наделив new путем вызова delete.

Например:

for (unsigned int i = 0; i < vector.size(); ++i)
{
    delete vector[i];
    vector[i] = NULL; 
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню