Я предполагаю, что Вы обращаетесь к репозиториям, когда Вы обращаетесь к 'сайту'
(Вещь, Вы выбираете из 'источников программного обеспечения')
, различия могут быть:
Тем не менее Все репозитории периодически синхронизируются, чтобы иметь Точно то же содержание. , Таким образом, действительно не имеет значения, какой repo Вы выбираете.
Как примечание стороны, Этот поток QA имеет информацию о том, как выбрать зеркало для увеличения скорости загрузки.
std :: vector
будет управлять памятью за вас, как всегда, но эта память будет состоять из указателей, а не объектов.
Это означает, что ваши классы будут потеряны в памяти, как только ваш вектор будет перемещен вне рамок. Например:
#include <vector>
struct base
{
virtual ~base() {}
};
struct derived : base {};
typedef std::vector<base*> container;
void foo()
{
container c;
for (unsigned i = 0; i < 100; ++i)
c.push_back(new derived());
} // leaks here! frees the pointers, doesn't delete them (nor should it)
int main()
{
foo();
}
Что вам нужно сделать, так это убедиться, что вы удалили все объекты до того, как вектор выйдет из области видимости:
#include <algorithm>
#include <vector>
struct base
{
virtual ~base() {}
};
struct derived : base {};
typedef std::vector<base*> container;
template <typename T>
void delete_pointed_to(T* const ptr)
{
delete ptr;
}
void foo()
{
container c;
for (unsigned i = 0; i < 100; ++i)
c.push_back(new derived());
// free memory
std::for_each(c.begin(), c.end(), delete_pointed_to<base>);
}
int main()
{
foo();
}
Это трудно поддерживать, потому что мы должны помнить о выполнении некоторых действий. Что еще более важно, если между выделением элементов и циклом освобождения произойдет исключение, цикл освобождения никогда не запустится, и вы все равно застрянете с утечкой памяти! Это называется безопасностью исключений и является важной причиной, по которой освобождение должно выполняться автоматически.
Было бы лучше, если бы указатели удаляли сами себя. Тезисы называются умными указателями, а стандартная библиотека предоставляет std :: unique_ptr
и std :: shared_ptr
.
std :: unique_ptr
представляет собой уникальный (без общего доступа, с одним владельцем) указатель на некоторые ресурс. Это должен быть ваш умный указатель по умолчанию и полная полная замена любого использования необработанного указателя.
auto myresource = /*std::*/make_unique<derived>(); // won't leak, frees itself
std :: make_unique
отсутствует в стандарте C ++ 11 по надзору, но вы можете создать его самостоятельно. Чтобы напрямую создать unique_ptr
(не рекомендуется вместо make_unique
, если вы можете), сделайте следующее:
std::unique_ptr<derived> myresource(new derived());
Уникальные указатели имеют только семантику перемещения; они не могут быть скопированы:
auto x = myresource; // error, cannot copy
auto y = std::move(myresource); // okay, now myresource is empty
И это все, что нам нужно, чтобы использовать его в контейнере:
#include <memory>
#include <vector>
struct base
{
virtual ~base() {}
};
struct derived : base {};
typedef std::vector<std::unique_ptr<base>> container;
void foo()
{
container c;
for (unsigned i = 0; i < 100; ++i)
c.push_back(make_unique<derived>());
} // all automatically freed here
int main()
{
foo();
}
shared_ptr
имеет семантику копирования с подсчетом ссылок; это позволяет нескольким владельцам совместно использовать объект. Он отслеживает, сколько shared_ptr
существует для объекта, и когда последний перестает существовать (этот счет становится равным нулю), он освобождает указатель. Копирование просто увеличивает количество ссылок (а перемещение передает право собственности по более низкой, почти бесплатной цене). Вы создаете их с помощью std :: make_shared
(или напрямую, как показано выше, но поскольку shared_ptr
должен выполнять внутреннее выделение памяти, его использование обычно более эффективно и технически более безопасно для исключений ] make_shared
).
#include <memory>
#include <vector>
struct base
{
virtual ~base() {}
};
struct derived : base {};
typedef std::vector<std::shared_ptr<base>> container;
void foo()
{
container c;
for (unsigned i = 0; i < 100; ++i)
c.push_back(std::make_shared<derived>());
} // all automatically freed here
int main()
{
foo();
}
Помните, обычно вы хотите использовать std :: unique_ptr
по умолчанию, потому что он более легкий. Кроме того, std :: shared_ptr
может быть построен из std :: unique_ptr
(но не наоборот), так что можно начать с малого.
В качестве альтернативы вы можете использовать контейнер, созданный для хранения указателей на объекты, таких как boost :: ptr_container
:
#include <boost/ptr_container/ptr_vector.hpp>
struct base
{
virtual ~base() {}
};
struct derived : base {};
// hold pointers, specially
typedef boost::ptr_vector<base> container;
void foo()
{
container c;
for (int i = 0; i < 100; ++i)
c.push_back(new Derived());
} // all automatically freed here
int main()
{
foo();
}
Хотя boost :: ptr_vector
явно использовался в C ++ 03, я не могу говорить об актуальности сейчас, потому что мы можем использовать std :: vector
с небольшими или отсутствующими сопоставимыми накладными расходами, но это утверждение следует проверить.
Тем не менее, никогда не освобождает явным образом элементы в вашем коде . Подведите итог, чтобы убедиться, что управление ресурсами выполняется автоматически. В вашем коде не должно быть необработанных указателей-владельцев.
По умолчанию в игре я, вероятно, выбрал бы std :: vector
. Мы в любом случае ожидаем совместного использования, это достаточно быстро, пока профилирование не говорит об обратном, это безопасно и просто в использовании.
std :: vector >
, вероятно, практически без сопоставимых накладных расходов, но это утверждение следует проверить.
Тем не менее, никогда не освобождает явно вещи в вашем коде . Подведите итог, чтобы убедиться, что управление ресурсами выполняется автоматически. У вас не должно быть необработанных указателей владения в вашем коде.
По умолчанию в игре я, вероятно, выбрал бы std :: vector
. Мы в любом случае ожидаем совместного использования, это достаточно быстро, пока профилирование не говорит об обратном, это безопасно и просто в использовании.
std :: vector >
, вероятно, практически без сопоставимых накладных расходов, но это утверждение следует проверить.
Тем не менее, никогда не освобождает явно вещи в вашем коде . Подведите итог, чтобы убедиться, что управление ресурсами выполняется автоматически. У вас не должно быть необработанных указателей владения в вашем коде.
По умолчанию в игре я, вероятно, выбрал бы std :: vector
. Мы в любом случае ожидаем совместного использования, это достаточно быстро, пока профилирование не говорит об обратном, это безопасно и просто в использовании.
Тем не менее, никогда явно не освобождает вещи в вашем коде . Подведите итог, чтобы убедиться, что управление ресурсами выполняется автоматически. У вас не должно быть необработанных указателей владения в вашем коде.
По умолчанию в игре я, вероятно, выбрал бы std :: vector
. Мы в любом случае ожидаем совместного использования, это достаточно быстро, пока профилирование не говорит об обратном, это безопасно и просто в использовании.
Тем не менее, никогда явно не освобождает вещи в вашем коде . Подведите итог, чтобы убедиться, что управление ресурсами выполняется автоматически. В вашем коде не должно быть необработанных указателей-владельцев.
По умолчанию в игре я, вероятно, выбрал бы std :: vector
. Мы в любом случае ожидаем совместного использования, это достаточно быстро, пока профилирование не говорит об обратном, это безопасно и просто в использовании.
Я предполагаю следующее:
На ум приходят следующие вещи:
Проблема с использованием vector
заключается в том, что всякий раз, когда вектор неожиданно выходит из области видимости (например, когда генерируется исключение) вектор очищается после вас, но это освободит только память, которой он управляет для хранения указателя , но не память, выделенную для того, на что ссылаются указатели. Итак, функция GMan delete_pointed_to
имеет ограниченное значение, поскольку работает только тогда, когда ничего не происходит.
Что вам нужно сделать, так это использовать интеллектуальный указатель:
vector< std::tr1::shared_ptr<Enemy> > Enemies;
(Если ваша std lib поставляется без TR1, используйте вместо него boost :: shared_ptr
.)
За исключением очень редких угловых случаев (циклических ссылок), это просто устраняет проблему времени жизни объекта.
Правка : Обратите внимание, что GMan в своем подробном ответе тоже упоминает об этом.