如何初始化一个以结构为值的地图?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何初始化一个以结构为值的地图?相关的知识,希望对你有一定的参考价值。

我使用map作为ID - > value的关联数组,其中值是定义对象的结构:

#include <map>

struct category {
        int id;
        std::string name;
};

std::map<int, category> categories;

int main() {
        categories[1] = {1, "First category"};
        categories[2] = {2, "Second category"};

}

上面的代码用g ++编译,但有以下警告:

warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x

我在这里阅读了关于struct初始化的各种问题/答案,但我仍然有点困惑。我有一系列相关问题:

  1. 我可以添加编译器选项-std = c ++ 0x并完成警告,但仍然没有更明智的基础问题。如果我在类别结构中添加方法,事情会不会破裂?
  2. 以更符合C ++ 03的方式初始化此POD结构(类别)的最佳方法是什么?
  3. 基本上,我还不确定以某种方式而不是另一种方式做事的后果。这种关联数组(其中键是对象的ID)很容易用php,我仍然在学习在C ++中使用它的正确方法。在上面的代码中是否有任何我应该注意的事项?

编辑 以下问题是相关的,但在我第一次阅读时,我不明白答案: C++ initialize anonymous struct c++ Initializing a struct with an array as a member Initializing structs in C++

答案

在C ++(ISO / IEC 14882:2003)中,括号括起的表达式列表可用于在定义它的声明中初始化聚合类型的变量。

EG

struct S { int a; std::string b; };

S x = { 39, "Hello, World\n" };

聚合类型是一个数组或类,没有用户声明的构造函数,没有私有或受保护的非静态数据成员,没有基类,也没有虚函数。请注意,类聚合不必是POD类,并且任何数组都是聚合,无论它是数组的类型是聚合。

但是,括号括起的表达式列表仅作为聚合的初始化程序有效,通常不允许在其他上下文中使用,例如赋值或类构造函数的成员初始化列表。

在下一版本的C ++(C ++ 0x)的当前草案中,在更多上下文中允许括号括起的表达式列表(brace-init-list),并且当从这样的初始化列表初始化对象时,它被称为列表-初始化。

允许这样的列表的新上下文包括函数调用中的参数,函数返回,构造函数的参数,成员和基本初始值设定项以及赋值的右侧。

这意味着这在C ++ 03中无效。

int main() {
        categories[1] = {1, "First category"};
        categories[2] = {2, "Second category"};
}

相反,你可以做这样的事情。

int main() {
        category tmp1 = { 1, "First category" };
        category tmp2 = { 2, "Second category" };

        categories[1] = tmp1;
        categories[2] = tmp2;
}

另外。

int main() {
        category tmpinit[] = { { 1, "First category" },
                               { 2, "Second category" } };
        categories[1] = tmpinit[0];
        categories[2] = tmpinit[1];
}

或者,您可以考虑为您的类型制作工厂功能。 (您可以为您的类型添加构造函数,但这会使您的类成为非聚合,并且会阻止您在其他位置使用聚合初始化。)

category MakeCategory( int n, const char* s )
{
    category c = { n, s };
    return c;
}

int main()
{
    categories[1] = MakeCategory( 1, "First category" );
    categories[2] = MakeCategory( 2, "Second category" );
}
另一答案

在当前的C ++标准中,您可以使用初始化列表来初始化仅包含POD值的数组和结构。下一个标准(又名C ++ 0x或C ++ 1x)将允许在包含非POD类型的结构上执行相同的操作,例如:的std :: string。这就是警告的内容。

我建议你为category添加一个简单的构造函数,它接受id和name,然后简单地调用该构造函数:

#include <map>
#include <string>

struct category {
        category() : id(0), name() {}
        category(int newId, std::string newName)
         : id(newId), name(newName) {}

        int id;
        std::string name;
};

std::map<int, category> categories;

int main() {
        categories[1] = category(1, "First category");
        categories[2] = category(2, "Second category");

}
另一答案

我们正在使用的初始化类型仅在新兴的C ++标准C ++ 0x中引入,因此是警告和编译器选项。一些编译器,如g ++,已经支持一些新功能,但标准本身尚未被接受。它为我们所知道的C ++增加了许多新功能。你可以在Stroustrup's site上阅读更多内容。

初始化结构你可以添加一个ctor(自然地),例如

struct category {
        category(int i, const std::string& n): id(i), name(n) {}
        int id;
        std::string name;
};

然后按如下方式初始化地图:

categories[1] = category(1, "First category");

请注意,从const char*到string的隐式转换将在此处工作,否则您也可以使用const char*定义ctor。

另一答案

我知道这是旧的,但也可以使用

std::map<int, std::pair<std::string, int>> categories

要么:

std::map<int, std::tuple<std::string, int, double>> categories

如果需要更多。

另一答案

您需要的功能在C / C ++中称为聚合。通过搜索“聚合c ++”,你会发现许多信息详细说明了这些原因和方法。

1-如果我在类别结构中添加方法,事情会不会破坏?

除非该方法影响底层C ++内存布局,否则没有必要。例如,普通函数无关紧要,但虚函数会因为它可能在类成员之前布局。

2-以更符合c99的方式初始化此POD结构(类别)的最佳方法是什么?

使用构造函数作为其他响应者建议。

3-在上面的代码中是否有任何我应该注意的事项?

它可能涉及冗余副本,具体取决于您如何设计构造函数。但是只有你经常需要初始化并且你真的关心性能才有意义。

以上是关于如何初始化一个以结构为值的地图?的主要内容,如果未能解决你的问题,请参考以下文章

如何(有效地)以地图为值插入地图?

在火花中创建一个以字长为键、以排序字为值的字典?

读取以第一列为键,其余为值的制表符分隔文件

从以数组为值的哈希中获取数组

以json为值的Elasticsearch java api更新API

二进制图片如何转化为值