Как вручную назначить размер вектора? - PullRequest
0 голосов
/ 30 января 2019

В моем приложении есть часть, которая требует от меня сделать копию контейнера.На данный момент я использую std :: vector (но может рассмотреть возможность использования чего-то другого).Приложение очень чувствительно в отношении задержки.Итак, я искал способ сделать копию вектора как можно быстрее.Я обнаружил, что memcpy делает это лучше, чем все остальное.Тем не менее, это не меняет внутренний размер вектора.Т.е. vector.size () все равно даст мне 0.

Я знаю, по какому скользкому пути я иду.Я не против выбросить проверки безопасности.Я знаю, сколько элементов копируется.Я не хочу использовать vector.resize () для изменения размера целевого вектора (это медленная операция).

Вопрос:

std::vector<my_struct> destination_vector;
destination_vector.reserve(container_length);
std::memcpy(destination_vector.data(), original_vector.data(), sizeof(my_struct)*container_length);

После кода, приведенного выше, мне нужно сообщить моему destination_vector, какой он размер.Как мне это сделать?

Спасибо.

Ответы [ 3 ]

0 голосов
/ 30 января 2019

Ваш фрагмент имеет неопределенное поведение, вы не можете memcpy в пустой вектор, даже если у вас есть reserved пробел.Это также может быть неопределенное поведение для memcpy любых my_struct объектов, если это не тип TriviallyCopyable .

Вы можете построить вектор какКопия источника напрямую. Скорее всего, ваш компилятор будет выдавать код, идентичный (или более быстрый), чем ваш исходный фрагмент, если my_struct имеет TriviallyCopyable.

std::vector<my_struct> destination_vector(original_vector.begin(), original_vector.begin() + container_length);
0 голосов
/ 30 января 2019

Как вручную назначить размер вектора?

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

После приведенного выше кода мне нужно сообщить моему destination_vector, какой он размер.Как мне это сделать?

Вышеупомянутый код имеет неопределенное поведение, поэтому не имеет значения, что вы делаете после него.

Простой и эффективный способ скопировать векторэто:

std::vector<my_struct> destination_vector(original_vector);
0 голосов
/ 30 января 2019
  1. Вы должны на самом деле resize() вектор, прежде чем скопировать материал в него, используя memcpy():

    destination_vector.resize(container_length);

    Но было бы лучше, во-первых, избегать использования memcpy() и использовать механизмы для копирования vector контента, предлагаемого vector, как предлагается в других ответах:

    std::vector<my_struct> destination_vector(original_vector);

    или, если экземпляр destination_vector уже существует:

    destination_vector.insert(destination_vector.begin(), original_vector.begin(), original_vector.end);

    или, самый быстрый, если вам больше не нужен оригинальный контент:

    destination_vector.swap(original_vector);

    Все эти варианты будут такими же быстрыми или даже более быстрыми, чем ваш memcpy() вариант.Если вы испытываете медлительность, см. 2.:

  2. Вероятно, у вас есть нетривиальный конструктор по умолчанию в my_struct.Удалите его или вставьте тривиальный (пустой) конструктор по умолчанию, чтобы ускорить процесс (чтобы избежать создания многих элементов, которые вы никогда не используете).

  3. Если my_struct содержит данные, не относящиеся к PODчлены (например, std::string), вы вообще не можете использовать memcpy().

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

resize() не является медленной операцией.Это так же быстро, как любое распределение памяти.

Есть ли у my_struct нетривиальный конструктор по умолчанию?Удалите его и позаботьтесь об инициализации вручную.Это может быть причиной того, что вы говорите resize() медленно.Это на самом деле построит ваши объекты.Но так как вы, очевидно, можете memcpy() ваши объекты, вы, вероятно, можете обойтись тривиальным (пустым) конструктором по умолчанию.

...