动态控制c ++数据结构中的成员数

时间:2012-10-22 01:40:34

标签: c++ optimization data-structures c++11 containers

我目前正在编写一个处理数据库的程序。

我可以要求不同的选项并获得可变数量的列。

问题是数据将是千兆字节的信息,我无法使用所有可能的选项制作一个结构。我需要能够动态创建一个只包含我需要的成员的结构,而不是别的。

我还想为每个可能的案例创建一个更好的结构!

以下是表格的示例:

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;
}

任何可以帮助加快速度的优化?

2 个答案:

答案 0 :(得分:1)

如果您愿意使用Boost库,可以采取以下建议。

您可以尝试使用boost::variant<list of possible types>的二维数组。对于动态二维数组,您可以使用boost::multi_array

根据文档,boost::variant有一个:

  

高效实施 - 尽可能基于堆栈(参见本节)   有关详细信息,请致电“"Never-Empty" Guarantee”

我之前成功使用了boost::variant的向量来表示数据库行,但我的内存要求比你的要小得多。你可能需要对这种方法进行基准测试,看看它是否可行。

如果使用此方法,则可能需要某种方法在运行时确定给定数据库列的索引。如果要按名称访问列,可以使用std::mapboost::unordered_map来执行列名和列索引之间的映射。

希望这有帮助。

答案 1 :(得分:0)

如何使用链接列表。您可以使用new运算符动态地为每个节点分配内存。

如果使用预定义的结构,性能可能不等于您将获得的性能,但它提供了更多的控制。

如果您仍想创建动态结构,则可以在结构内部使用联合。

更多信息:Dynamic structures in C++