在C ++中,我经常需要使用一个非常简单的,包含各种数据类型的原始对象,以便可以在函数之间轻松传递它。在Python中,我通过使用字典来实现这一点。例如:
easy = {"keyframe_range":[], "value":0.25, "interpolation":"bezier"}
但是,在C ++中,如果我想创建类似的内容,则需要:
struct obj
{
vector<int> keyframe_range;
float value;
string interpolation;
obj(vector<int> vv, float ff, string ss) : keyframe_range(vv), value(ff), interpolation(ss) {}
};
obj easy(vector<int>(), 0.25, "bezier");
当我需要一时兴起地创建知道谁的对象时,为我需要的每个对象手动编写一个参数化的构造函数是非常低效率的,而且浪费大量时间。在Python中,我基本上可以使用字典来避免这种情况;但是,C ++中的unordered_maps必须映射到相同的数据类型,因此它们并不是我真正想要的。
本质上,我只是想要一种简单的方法来创建一个简单的对象,该对象充当各种数据类型的项目的集合,仅此而已。可以在C ++ 11中完成吗?如果可以,怎么办?
答案 0 :(得分:9)
手动编写效率极低并且浪费大量时间 我需要的每个对象的参数化构造函数。
我完全同意。但是,这没有问题,因为您实际上不需要为每个简单的结构编写构造函数:
#include <vector>
#include <string>
#include <iostream>
struct obj
{
std::vector<int> keyframe_range;
float value;
std::string interpolation;
};
int main() {
obj easy{ {}, 0.25, "bezier"};
std::cout << easy.value << " " << easy.interpolation;
}
它称为aggregate initialization,可以在课程有
时完成
没有私有或受保护的直接(自C ++ 17起)非静态数据成员
没有用户声明的构造函数(直到C ++ 11)
没有用户提供的构造函数(允许使用明确的默认或删除的构造函数)(自C ++ 11起)(直到C ++ 17)
不允许用户提供,继承或显式的构造函数(允许使用显式默认或删除的构造函数)(自C ++ 17起)(直到 C ++ 20)
没有用户声明或继承的构造函数 [...]
以及其他一些限制,通常都适用于这种简单的结构(它们称为集合)。
本质上,我只是想要一种简单的方法来创建简单的对象 它充当各种数据类型的项目的集合,什么也没有 更多。可以在C ++ 11中完成吗?如果可以,怎么办?
或者,您应该看一下std::tuple
,尽管编写自己的类的好处是为成员提供了有意义的名称,并且您可以区分与std::tuple
完全相同的类型。
另一方面,std::tuple
的优点是它附带了已经定义的几个运算符(例如operator<
)。因此,根据您的用例,您可以选择其中一个。
答案 1 :(得分:5)
您可以使用std::tuple
。它使您可以创建异构类型的对象,而不必指定所有样板。它确实有缺点。您不能给元组成员起名字。您必须通过它们的“索引”(第一个成员是索引0)或类型(仅当您不重复这些类型时才有效)来访问它们。所以
easy = {"keyframe_range":[], "value":0.25, "interpolation":"bezier"}
将成为
auto easy = std::tuple<std::vector<int>, float, std::string>{{}, 0.25, "bezier"}
您可以访问std::get<1>(easy)
/ std::get<float>(easy)
之类的成员以获得float
成员。
C ++ 17:您可以使用structured binding来获得对像这样的成员的命名访问
auto&[easy_vec, easy_float, easy_string] = easy;
现在easy_vec
,easy_float
和easy_string
是对元组成员的引用。