具有可变大小和变量类型的 C++ 容器
c++ container with with variable size and variable types
我正在尝试创建类似列表的东西。但是,列表的不同实例可能具有不同数量的条目,并且条目类型基于用户给出的输入。例如,用户声明他们希望列表中每个条目的结构包含一个 int id、一个 std::string name、一个双 metricA 和一个长 metricB。基于此输入,将创建以下内容:
struct some_struct {
int id;
std::string name;
double metricA;
long metricB;
}
list<some_struct> some_list;
用户输入可以从文件中读取,在屏幕上输入等。 此外,some_struct中的条目数量可变。换句话说,它可能具有上面列出的条目,它可能只有其中的 2 个,或者它可能有 10 个完全不同的条目。有没有办法创建这样的结构?
此外,必须能够将比较运算符应用于some_struct的每个成员。我可以使用 boost::any 来存储数据,但这会产生比较运算符的问题,并且还会产生比理想情况更多的开销。
C++是一种强类型语言,这意味着您必须声明数据结构类型。为此,您不能声明具有任意数量或类型的成员的struct
,必须预先知道它们。
当然,现在有办法在C++处理这些问题。仅举几例:
- 使用映射(
std::map
或std::unordered_map
(创建"表"而不是结构。将字符串映射到字符串,即将名称映射到值的字符串表示形式,并将它们解释到您的内心。 - 使用预制变体类型,如
boost::any
. - 使用多态性 - 将指针存储在列表中,并对值调用虚拟机制调度操作。
- 为输入语言创建类型系统。然后具有每种类型的值表,并从列表中指向相应的表。
可能还有与程序员C++一样多的其他方法。
有很多方法可以解决具有不同成员的数据结构问题,哪种方法最好在很大程度上取决于它的确切使用方式。
最明显的是使用继承。 您可以从基类派生所有可能性:
struct base_struct {
int id;
std::string name;
};
list<base_struct*> some_list;
struct some_struct : public base_struct {
double metricA;
};
struct some_other_struct : public base_struct {
int metricB;
};
base_struct *s1 = new some_struct;
s1->id = 1;
// etc
base_struct *s2 = new some__other_struct;
s2->id = 2;
// etc
some_list.push_back(s1);
some_list.push_back(s2);
棘手的一点是,您必须确保在将元素取出时,情况适当。 dynamic_cast
可以以类型安全的方式执行此操作:
some_struct* ss = dynamic_cast<some_struct*>(some_list.front());
您可以在使用type_info
在强制转换之前查询名称:
typeid(*some_list.front()).name();
请注意,这两者都需要使用 RTTI 进行构建,这通常没问题,但并非总是如此,因为 RTTI 具有性能成本并且可能会增加内存占用,尤其是在广泛使用模板的情况下。
在以前的项目中,我们使用 boost any 处理了类似的事情。 any
的优点是它允许您混合不是从彼此派生的类型。 回想起来,我不确定我会再次这样做,因为它使代码在运行时有点太容易失败,因为类型检查被推迟到那时。 (dynamic_cast
方法也是如此。
在糟糕的旧 C 时代,我们用一个union
解决了同样的问题:
struct base_struct {
int id;
std::string name;
union { // metricA and metricB share memory and only one is ever valid
double metricA;
int metricB;
};
};
同样,您遇到了一个问题,您必须自己确保它是正确的类型。
在STL之前的时代,许多容器系统被编写为采用void*
,再次要求用户知道何时投射。 理论上,您仍然可以通过说list<void*>
来做到这一点,但您无法查询类型。
编辑:永远不要使用void*
方法!
我最终使用了一个带有 boost::variant 的列表。性能比使用 boost::any 要好得多。事情是这样的:
#include <boost/variant/variant.hpp>
#include <list>
typedef boost::variant< short, int, long, long long, double, string > flex;
typedef pair<string, flex> flex_pair;
typedef list< flex_pair > row_entry;
list< row_entry > all_records;
- 从模板创建通用打印函数,以打印基元数据类型变量的值
- 指针数据类型变量如何包含对象?
- 将 static_cast<int>(-15) 分配给静态常量字符类型变量
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- 如何为结构类型变量赋值
- 如何将字符类型变量附加到字符串中?
- 共享或私有 openmp 代码中的结构化类型变量
- 有没有办法在 c++ 中制作类型变量?
- 从其他类声明类类型变量会给出 C2143 错误(在"*"之前缺少";")
- 如何检查类中定义的枚举类型变量是否被分配给?
- 将子类实例保存在父类型变量中并通过父变量使用 Child 函数?
- 是否可以在没有结构的情况下创建新的类型变量?
- 为什么类型变量;不调用默认 CTR
- 如何使用CIN将输入整数值获取到char类型变量中
- 如何为 char** 类型变量提供适当的值,以便将其分配给字符串变量
- 在C++标准中哪里说必须初始化 const 内置类型变量的定义
- 为什么可以将其他类型变量用作C 中常量参考参数参数的参数
- Eclipse CDT 打开声明的自动类型变量
- 如何计算长长类型变量中的位数
- 将自动类型变量初始化为零.这种类型安全吗?