【问题标题】:vector of variable type vectors变量类型向量的向量
【发布时间】:2017-07-26 05:39:58
【问题描述】:

我目前正在用 C++ 实现一个大表的数据存储。该表需要能够为可变数量的列中的每一个存储不同的数据类型。

每列的类型和长度都是在运行时定义的。因此,我认为,一个指向向量的向量将是正确的方法。但是,我无法弄清楚如何使用可变数据类型来做到这一点。

我查看了How to get a vector of different vectors in C++,但没有动态解决方案。

我对任何其他解决方案持开放态度,我不一定需要向量,但表格应该在运行时重新调整大小。

它应该看起来像这样:

0  1  2  3    ...
-  -  -  -    -
1  a  0  1.3  ...
2  b  1  2.5  ...
3  c  0  1.5  ...
4  d  0  0.8  ...
5  e  1  1.2  ...
.. .. .. ...  ...

我有些人建议使用 boost::any,但我有点不情愿(就效率而言),因为表必须从磁盘加载大数据包文件。

【问题讨论】:

  • 您想在向量中使用任意类型的数据?它必须基于单元格或列是任意的?请添加您想要实现的最小伪代码示例...
  • 表格在列方面必须是任意的。在每一列中,数据类型保持不变。我在最初的问题中添加了一个小图表
  • 你不喜欢 boost::any “在效率方面”,与什么相比?你有没有实际测量过它比 void*s 变成一个巨大的 char[] 慢得令人无法接受?
  • 到目前为止我还没有测量过这个。我目前正在尝试找出我有哪些选择。如果我必须在一个整数列中汇总超过 10000 个条目,那么将它们存储为字符串并在每次我需要访问它们时强制转换它们似乎非常低效。

标签: c++ vector dynamic


【解决方案1】:

在 boost 中实现的 any 类将满足您的需求。

这是一个如何在他们的网站上使用它的示例:

#include <vector>
#include <boost/any.hpp>

using boost::any_cast;
typedef std::vector<boost::any> many;

void append_int(many & values, int value)
{
    boost::any to_append = value;
    values.push_back(to_append);
}

void append_string(many & values, const std::string & value)
{
    values.push_back(value);
}

void append_char_ptr(many & values, const char * value)
{
    values.push_back(value);
}

void append_any(many & values, const boost::any & value)
{
    values.push_back(value);
}

void append_nothing(many & values)
{
    values.push_back(boost::any());
}

【讨论】:

  • 我也遇到过这种情况,但是我想知道它的效率如何?我必须从磁盘读取大数据包来填满表格。这些文件的大小可以超过 1 GB。
  • Boost.Any 不是容器。
  • @Phil333 如果您担心效率,请考虑将所有数据存储为字符串,然后在必要时进行转换。 boost::any 很有可能会更胜一筹。
  • @LightnessRacesinOrbit 看这里:boost.org/doc/libs/1_61_0/doc/html/boost/any.html: class any {
  • 哈,我错了;认为这将是一个类模板,但这没有任何意义。 :)
【解决方案2】:

如果您不能使用 boost 并且不想重新实现 boost::any,您可以使用 void * 作为穷人的 any 容器。表级别将是std::vector&lt;void *&gt;,每列(T 类型)将是std::vector&lt;T&gt;。然后依次分配每一列,并将列的地址存储在初始的std::vector&lt;void *&gt;中。

如果您在使用它之前转换了每列的值,它应该可以工作。根据您的要求,正确实现它可能或多或少简单,因为您有原始指针,您应该仔细实现析构函数,并在适当的情况下复制移动构造函数和赋值或声明它们已删除。但它是(穷人的)提升替代品......

【讨论】:

  • 我确实可以使用 boost,并且我在我的程序的其他部分使用它。但我担心在处理必须执行数值运算的大型数据集时,将所有数据转换为字符串效率有点低。
【解决方案3】:

在向量中存储不同的类型是不可能的,但是如果你存储没有类型的指针(void*),那么你可以将它重新输入为任何你想要的类型。如果你在运行时不知道你在读什么类型,那么让结构包含指针 void* 和变量来确定类型。

自从我使用 C++ 以来,示例可能只是伪 C++。

#include<vector>
#include<iostream>

void workWithCharArray(char* c);

typedef struct mytype {
    int type = 0;   // this defining default values is available since C++11
    void* var = nullptr;
} Mytype;

int main() {
    char* ptr = (char*)"Testing string";
    std::vector<Mytype> container;
    Mytype tostore;
    tostore.type = 1;
    tostore.var = (void*)ptr;

    container.append(tostore);

    switch (tostore.type) {
        case 1:
            workWithCharArray((char*)tostore.var);
            break;
        default:
            std::cerr << "Unknown type - Error handling";
    }

    return 0;
}

void workWithCharArray(char* c) {
    std::cout << c << std::endl;
}

【讨论】:

    【解决方案4】:

    如果您需要一个存储不同数据类型的一维向量的二维向量,您可以为内部向量创建一个抽象的、非模板化的基类,然后将指向该抽象基类的指针存储在外部向量中,如果你想在抽象向量上调用成员函数,则利用多态性。

    class AbstractVector {
        ... // provide pure virtual interface here
    }
    
    template<class T>
    class MyVector : public AbstractVector, public std::vector<T> { 
        ... /* provide implementation of pure virtual interface using 
               already available functionality from std::vector here */
    }
    

    然后,在您的实现中,您可以存储指向基类 AbstractVector(或 unique_ptrsshared_ptrs,具体取决于您想要做什么)的指针:

    std::vector<AbstractVector *> table;
    MyVector<int> * columnOne = new MyVector<int>;
    MyVector<float> * columnTwo = new MyVector<float>;
    table.push_back(columnOne);
    table.push_back(columnTwo);
    

    【讨论】:

      猜你喜欢
      • 2023-03-31
      • 2016-08-30
      • 2017-03-26
      • 2018-05-05
      • 2016-02-15
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      • 2020-07-14
      相关资源
      最近更新 更多