我目前正在编写一个处理数据库的程序。
我可以要求不同的选项并获得可变数量的列。
问题是数据将是千兆字节的信息,我无法使用所有可能的选项制作一个结构。我需要能够动态创建一个只包含我需要的成员的结构,而不是别的。
我还想为每个可能的案例创建一个更好的结构!
以下是表格的示例:
smallint(6) - varchar(255) - double - int(11)
smallint(6) - varchar(255) - double - double - double - int(11)
smallint(6) - smallint(6) - varchar(255) - varchar(255) - double - int(11)
有没有办法在c ++中创建具有动态数量成员的结构,这些结构与普通结构一样高效?
[编辑]
这是使用@Indus-抗抑郁药理念的解决方案。它有效,但唯一的问题似乎比普通结构慢4倍。
#include <windows.h>
class Column
{
public:
Column(uint64 nOffset, const type_info* pType)
{
m_nOffset = nOffset;
m_pType = pType;
}
uint64 m_nOffset;
const type_info* m_pType;
};
struct UWElement
{
public:
template<class T>
void Set(uint64 nColumn, T value)
{
if ((*m_pColumnList)[nColumn].m_pType == &typeid(T))
{
uint64 nOffset = (*m_pColumnList)[nColumn].m_nOffset;
*(reinterpret_cast<T*>(m_pData + nOffset)) = value;
}
else
{
assert(0);
}
}
template<class T>
T& Get(uint64 nColumn)
{
// No type check here to test speed
uint64 nOffset = (*m_pColumnList)[nColumn].m_nOffset;
return *reinterpret_cast<T*>(m_pData + nOffset);
}
protected:
unsigned char* m_pData;
std::vector<Column>* m_pColumnList;
friend class UWElementList;
};
class UWElementList
{
public:
UWElementList()
{
m_nEndOffset = 0;
}
template<class T>
void AddType()
{
Column column(m_nEndOffset, &typeid(T));
m_columnlist.push_back(column);
m_nEndOffset += sizeof(T);
}
void CreateElement()
{
UWElement element;
element.m_pData = new unsigned char[m_nEndOffset];
element.m_pColumnList = &m_columnlist;
m_elementList.push_back(element);
}
UWElement& operator[](int64 nPos)
{
return m_elementList[nPos];
}
private:
std::vector<Column> m_columnlist;
uint64 m_nEndOffset;
std::vector<UWElement> m_elementList;
};
int main()
{
struct SimilarStruct
{
double a;
int b;
int c;
};
SimilarStruct similar;
vector<SimilarStruct> similarList;
similarList.push_back(similar);
UWElementList list;
list.AddType<double>();
list.AddType<int>();
list.AddType<int>();
list.CreateElement();
// Test writing speed
uint64 nTick = GetTickCount64();
for(int i=0; i<100*1000*1000; i++)
{
//list[0].Set<double>(0,(double)1.1); //Speed 140ms
list[0].Get<double>(0) = (double)1.1; //Speed 109ms
//similarList[0].a = (double)1.1; //Speed 31ms
}
cout << GetTickCount64() - nTick << endl;
double d=0;
// Test reading speed
nTick = GetTickCount64();
for(int i=0; i<100*1000*1000; i++)
{
d += list[0].Get<double>(0); //Speed 94ms
//d += similarList[0].a; //Speed 93ms
}
cout << GetTickCount64() - nTick;
return d;
}
任何可以帮助加快速度的优化?
答案 0 :(得分:1)
如果您愿意使用Boost库,可以采取以下建议。
您可以尝试使用boost::variant<list of possible types>
的二维数组。对于动态二维数组,您可以使用boost::multi_array
。
根据文档,boost::variant
有一个:
高效实施 - 尽可能基于堆栈(参见本节) 有关详细信息,请致电“"Never-Empty" Guarantee”。
我之前成功使用了boost::variant
的向量来表示数据库行,但我的内存要求比你的要小得多。你可能需要对这种方法进行基准测试,看看它是否可行。
如果使用此方法,则可能需要某种方法在运行时确定给定数据库列的索引。如果要按名称访问列,可以使用std::map
或boost::unordered_map
来执行列名和列索引之间的映射。
希望这有帮助。
答案 1 :(得分:0)
如何使用链接列表。您可以使用new运算符动态地为每个节点分配内存。
如果使用预定义的结构,性能可能不等于您将获得的性能,但它提供了更多的控制。
如果您仍想创建动态结构,则可以在结构内部使用联合。