繁体   English   中英

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

[英]How do you initialize a map which takes a struct as value?

我使用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 ++初始化匿名结构
c ++使用数组作为成员初始化结构
在C ++中初始化结构

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

例如

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。 这就是警告的内容。

我建议你将一个简单的构造函数添加到带有id和name的category ,然后简单地调用该构造函数:

#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的网站上阅读更多内容。

初始化结构你可以添加一个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-在上面的代码中是否有任何我应该注意的事项?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM