#c #casting
#c #Кастинг
Вопрос:
Я бы хотел избавиться от этого дополнительного уровня косвенности, поскольку это будет критично для производительности. В частности, массив с именем ‘componentPoolsArray[8]’, в нем хранятся указатели, указывающие на динамически выделяемые пулы. Я бы хотел встроить объекты пула непосредственно в массив, но это будут объекты пула разных типов. Они будут отличаться только типом внутреннего указателя, хранящегося в векторе, а не размером, вот почему я думаю, что мог бы привести или что-то в этом роде:
struct HomogenousComponentPoolBaseClass {};
template <typename T_Component>
struct HomogenousComponentPool : HomogenousComponentPoolBaseClass
{
std::vector<T_Component> componentPool;
};
struct ComponentTypeA { int component_A_Member; };
struct ComponentTypeB { int component_B_Member; };
struct ComponentTypeC { int component_C_Member; };
HomogenousComponentPoolBaseClass* componentPoolsArray[8]; // Pointers to component pools, will be heap-allocated
// The only reason I used inheritance here is so I could get it to compile by
// declaring pointers to a base class
int main()
{
// Create new pool of ComponentTypeA
componentPoolsArray[0] = new HomogenousComponentPool<ComponentTypeA>;
// Create a new component in that pool
static_cast<HomogenousComponentPool<ComponentTypeA>*>
(componentPoolsArray[0])->componentPool.push_back(ComponentTypeA());
// Access the first component object from that pool
static_cast<HomogenousComponentPool<ComponentTypeA>*>
(componentPoolsArray[0])->componentPool[0].component_A_Member;
}
Поэтому я хотел бы встроить ‘class HomogenousComponentPool<T_Component>’ непосредственно в ‘componentPoolsArray[0]’. Насколько я понимаю, я могу сделать это несколькими способами, но я не уверен, какой из них лучше и даже безопасен ли вообще:
template <typename T_Component>
struct HomogenousComponentPool // No inheritance
{
std::vector<T_Component> componentPool;
};
struct ComponentTypeA { int component_A_Member; };
struct ComponentTypeB { int component_B_Member; };
HomogenousComponentPool<char> componentPoolsArray[8]; // The class is built directly into the array.
// Here I've selected 'char' as the template type, which means that HomogenousComponentPool
// will have std::vector<char> as the componentPool. Since the vector should only store pointers
// then I figured casting to another type won't matter.
int main()
{
// Create new pool of ComponentTypeA directly into array
componentPoolsArray[0] = HomogenousComponentPool<char>();
// Create a new component in that pool
// I can either cast the outside class
reinterpret_cast<HomogenousComponentPool<ComponentTypeA>amp;>
(componentPoolsArray[0]).componentPool.push_back(ComponentTypeA());
// Or the inside std::vector
reinterpret_cast<std::vector<ComponentTypeA>amp;>(componentPoolsArray[0].componentPool).push_back(ComponentTypeA());
}
Является ли это законным кодом? Я думал об использовании нескольких методов, включая указатели void, но я не знаю, как я могу сделать это безопасно. Я бы сделал это только в том случае, если бы выступление было действительно важным
Комментарии:
1. Не хочу перескакивать на пользователя с более чем 8000 репутациями, но … проводили ли вы какое-либо тестирование производительности приложения, чтобы убедиться, что именно здесь необходима оптимизация? Иногда преждевременная оптимизация действительно является корнем всего зла.
2. Это похоже на преждевременную оптимизацию. Если вы так сильно заботитесь о perf, держу пари, вы можете сэкономить гораздо больше, чем косвенное обращение с указателем, используя другие методы. Но, допустим, вы пишете код так быстро, что дополнительная косвенность фактически снижает производительность. В подобных случаях иногда вам просто нужно нарушить безопасность типов. Не такая уж большая проблема, ИМО, если она хорошо инкапсулирована, чтобы
void*
не просачивалась за пределы непосредственной области, в которой она необходима. Распределители памяти обычно хранят память в виде массивовunsigned char
и при необходимости приводят к нужному типу.3. Второй способ небезопасен. A
vector<char>
— это не avector<something_else>
. (Хотя на практике это, вероятно , работает, гарантии нет. Вам также нужно вручную очистить вектор.) Что могло бы работать лучше, так это использовать объединение, либо вектор объединений, либо объединение векторов (что и пытается сделать ваш второй способ, но тогда он будет использовать надлежащую поддержку языка).4. Возможно, стоит взглянуть на std::variant .
5. @Tumbleweed53 Только второй? Но первое приведение — это приведение T<char> к T<ComponentTypeA> , это также не тот тип класса, к которому я его привел. Есть разница с std::vector? Дело в том, что если я приведу внешний класс вместо std::vector, компилятор будет обрабатывать этот std::vector<char> как std::vector<something_else> в любом случае, нет?