C ++: Что вставлять в векторы - указатели или ссылки, когда вектор копирует свои элементы? - PullRequest
1 голос
/ 24 ноября 2011

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

Теперь vector :: push_back (...) работает над вызовом по ссылке (а не вызовом по значению), поэтому в первый момент переданный объект не копируется. Но как насчет позже? Хранит ли вектор внутри указатели или прямые ссылки? Когда необходимо расширить вектор, копируются ли сами содержащиеся элементы или их адреса?

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

Ответы [ 3 ]

2 голосов
/ 24 ноября 2011

std::vector::push_back сохраняет копию объекта.

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

std::vector<BigObject*> objects; //manage memory yourself

Или вы можете использовать какой-нибудь умный указатель, чтобы избежать управления памятью самостоятельно. Например, вы можете использовать std::unique_ptr, если ваш компилятор поддерживает это:

std::vector<std::unique_ptr<BigObject>> objects;

Если вы используете указатели (или умные указатели), то копирование все еще там, но на этот раз копирование выполняется для указателей (или умных указателей), что намного дешевле.

Из комментария @ Loki:

Или вы можете использовать boost::ptr_vector<>, который предназначен для хранения указателей и будет возвращать ссылки при доступе, упрощая тем самым использование стандартных алгоритмов, поскольку все они ожидают объекты.

2 голосов
/ 24 ноября 2011

vector::push_back(...) работает по вызову по ссылке (а не по вызову по значению), поэтому в первый момент переданный объект не копируется

vector::push_back() хранит копию добавляемого объекта.

Хранит ли вектор внутри указатели или прямые ссылки?

То, как вектор внутренне хранит элементы, является деталью реализации, но сложность и требования к поведению оставляют мало места для вариаций. Vector хранит элементы в смежных местах памяти, очень похожих на массивы.

Когда необходимо расширить вектор, копируются ли сами содержащиеся элементы или их адреса?

Когда вектор расширяется, ему нужно скопировать все объекты в новую непрерывную память, опять же, это деталь реализации. Если элементы являются указателями, то сами указатели будут скопированы.

Сами объекты должны храниться в векторе или, скорее, указатели на эти объекты. Есть ли какая-то лучшая практика для этого?

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

0 голосов
/ 28 марта 2014

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

Однако, если вы делаете больше и больше добавляете и удаляете вектор, чем указатели, указатели будут более эффективными.

...