LINUX.ORG.RU

Добавить вектор в вектор с максимальной производительностью

 , ,


0

1

Я создаю вектор в отдельном потоке, после этого мне его надо сохранить вызвав функцию Data::insert(). После сохранения изначальный вектор мне больше не нужен. Как лучше всего это сделать? Заранее спасибо.

template<typename DATA_TYPE>
class Data
{
public:
    Data();

    void insert(vector<DATA_TYPE>& d)
    {
        if (d.empty())
            throw range_error("Data::insert(): Vector is empty!");

        lock_guard<mutex> l(data_mutex_);
        // Add d to the vector data_
    }
private:
    vector<vector<DATA_TYPE>> data_;

    mutex data_mutex_;
};


Последнее исправление: ECLIPSE (всего исправлений: 1)
Ответ на: комментарий от crutch_master

Ссылка на него будет уничтожена после завершения потока. Я думал просто сделать:

data_.push_back(std::move(d));

Правильно ли это будет?

ECLIPSE
() автор топика
Ответ на: комментарий от ECLIPSE

Ссылка на него будет уничтожена после завершения потока.

Значит её не надо уничтожать, иначе тебе придётся вектор копировать, а это долго и под условие задачи не попадает.

crutch_master ★★★★★
()
Ответ на: комментарий от Deleted

Вообще я с тобой согласен, но так работает в принципе. Сам как раз смотрю почему так.

ECLIPSE
() автор топика
Ответ на: комментарий от Deleted

Так std::move её и производит. Можно конечно её и принимать, чтобы на стороне вызова было лучше видно, что происходит с аргументом.

xaizek ★★★★★
()
Ответ на: комментарий от ECLIPSE

Если в функции insert примешь его по rvalue-ссылке или по значению (и дальше при вставке сделаешь move), то правильно, иначе будет копироваться.

Softwayer ★★
()

Имхо, если важна производительность, то эта конструкция имеет некоторые проблемы:

vector<vector<DATA_TYPE>> data_;
По стандарту элементы вектора расположены в памяти последовательно, значит при каждом инсерте в data_ будет происходить перемещение элементов. Логичнее на мой взгляд сделать:
list<vector<DATA_TYPE>> data_;
А в методе инсерт сделать std::swap

spectral1989
()
Ответ на: комментарий от ECLIPSE

s/push_back/emplace_back/ и будет норм. push_back принимает const T& и твой std::move абсолютно бесполезен. А emplace_back позовет move конструктор, который отработает без копирования.

Это в предположении, что тебе действительно нужен vector<vector<T>>.

kawaii_neko ★★★★
()
Ответ на: комментарий от kawaii_neko

Начиная с С++11 у vector есть перегруженная версия с value_type&&.

Deleted
()
Ответ на: комментарий от Deleted

Точно, пропустил этот момент, название метода сбило) Но если realloc зафэйлится в попытке увеличить capacity объекта до нужного размера, чтобы вместить старые и новые данные всё равно прозойдёт перемещение в памяти всего объекта, подход всё равно критики не выдерживает.

spectral1989
()

Делай указатели на вектора и храни их. Не делай delete для вектора в потоке который его создал, делай delete при очистке вектора указателей. А без указателей ты никак копирования не избежишь.

KivApple ★★★★★
()
Последнее исправление: KivApple (всего исправлений: 1)

Альтернатива move semantics - shared_ptr. Ещё при царе горохе сиё работало. А чего в кишках у move конструктора vector'a надо ещё посмотреть.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Казалось бы, что там может быть кроме свопа трёх указателей (или одного указателя и двух size_t, что то же самое)

Softwayer ★★
()
Ответ на: комментарий от Softwayer

Возможно да, а возможно и нет. В любом случае, это соизмеримо со свопом трёх указателей, или с копированием двух и одним интристиком.

pon4ik ★★★★★
()
Ответ на: комментарий от spectral1989

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

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.