переместить конструктор излишним

У меня есть класс, который содержит указатель на большой кусок выделенной памяти и множество членов примитивного типа. Я разбираюсь с конструкторами ходов и думаю, что это прекрасная возможность использовать один из них. Очевидно, указатель должен быть перемещен, но idk, если это хорошая идея с примитивами.

Ниже приведен надуманный пример класса:

class Foo {
private:
long m_bar = 1;
/* 20+ similar members */
};

Чтобы сделать их подвижными, они должны быть динамически распределены.

class Foo {
public:
Foo(Foo && rhs) : m_bar(rhs.m_bar) { rhs.m_bar = nullptr; }
~Foo() { delete m_bar; }
private:
long *m_bar = new long{1};
};

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

4

Решение

Во всяком случае, я полагаю, что куча распределения каждого члена, как это будет в конечном итоге медленнее. Помимо начального выделения кучи, выполняемого только при построении, удержание указателей на многих небольших несмежных элементах данных в куче плохо сочетается со стратегиями кэширования ЦП.

Некоторые классы движутся очень хорошо, потому что у них большой бит памяти, выделенный в куче (например, std :: string). В вашем случае перемещение каждого указателя будет примерно таким же дорогим, как перемещение ваших меньших типов данных. Единственный способ увидеть, как это происходит быстрее, — это обернуть свои меньшие члены данных в класс / структуру, которая выделена в куче (возможно, содержит в нем unique_pointer.) И перемещать их все с помощью перемещения одного указателя.

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

6

Другие решения

Семантика перемещения выполняется быстрее, когда перемещение объекта происходит быстрее, чем его копирование. В вашем примере это не так. Копирование long должно быть с той же скоростью, что и копирование указателя на long. Добавление семантики перемещения путем динамического распределения каждого отдельного члена почти наверняка замедлит, а не ускорит.

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

2

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

Вы можете захотеть аннулировать оригиналы, но это не требует указателей.

1
По вопросам рекламы [email protected]