История такова: существует пул памяти фиксированного типа Pool
, в котором хранятся элементы некоторого типа T
. Обе проблемы, перечисленные в заголовке, были обнаружены при создании функции alloc()
, которая создает и добавляет новый элемент в пул:
template <class T, size_t qty, class Alloc = allocator<T>>
class Pool {
array <T*, qty> cells; // Pointers to pre-allocated memory
...
public:
T& alloc (...) { // [2] It is unknown what parameters T's constructor may take
T&& tmp (...); // [2] But I need them to be passed as they are
size_t cellNo = findEmptyCell(); // Returns the number of the cell
*cells[cellNo] = tmp; // Placing the new object into the pool
// [1] "invalid conversion from 'int&& (*)(...)' to 'int'" when T is int
isEmpty[cellNo] = false; // Marking the cell as occupied
return *cells[cellNo];
}
}
Итак, 1) как избежать копирования ненужных объектов в этом случае?
И 2) есть ли способ передать конструктору произвольные аргументы?
1 ответ
Вы ищете "идеальную пересылку" с помощью шаблона функции с переменным числом аргументов:
template <class... Args>
T& alloc(Args&&... args) {
size_t cellNo = findEmptyCell();
*cells[cellNo] = T(std::forward<Args>(args)...);
isEmpty[cellNo] = false;
return *cells[cellNo];
}
Это будет принимать любое количество аргументов и пересылать их (копировать для lvalues, перемещать для rvalues) в конструктор T
. Затем этому временному объекту будет назначено перемещение в *cells[cellNo]
.
*cells[cellNo] = T(std::forward<Args>(args)...);
и new (cells[cellNo]) T(forward<Args>(args)...);
в этом случае?
Похожие вопросы
Новые вопросы
c++
C ++ - это язык программирования общего назначения. Первоначально он был разработан как расширение C и имеет аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде (который должен быть) скомпилирован с помощью компилятора C ++. Используйте тег для конкретной версии для вопросов, связанных с конкретной версией стандарта [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] или [C ++ 23] и т. Д. .
T&& tmp (...);
Это объявление функции. Я предполагаю, что вы имели в виду что-то другое и использовали неправильный синтаксис. Кроме того, если я не ошибаюсь, ваш пул памяти не заполнен заранее созданными объектами, поэтому*cells[cellNo] = tmp
должен быть UB, если тип не POD. Просто используйте новое размещение.alloc()
вT()
, спасибо за объяснение ошибки [1]. Но почему*cells[cellNo] = tmp
должен генерировать UB?cells
указывают на предварительно выделенную память, поэтому следует просто использовать ее. Или вы имеете в виду, что это вызов дляoperator=
, который не определен для мусора, изначально находящегося в*cells[cellNo]
?operator=
. Если вы уже выделили память и создали там объект, он будет работать должным образом. Если объект не построен и не является POD, это вызовет UB. И, конечно, если вы не выделили память, она эффектно взорвется.