【问题标题】:g++ warning on declaring multidimensional, double array关于声明多维双数组的 g++ 警告
【发布时间】:2011-08-23 16:58:17
【问题描述】:

在我的 C++ 程序中,我试图用全 0 初始化一个 3*3*3 类型的 double 数组。 在类头文件中,我声明了一个成员

double list[3][3][3];

当我打印出这个数组的内容时,我发现并不是所有的条目都像我预期的那样为 0。例如list[1][1][1] 的值为 4.03158e-321

因此我在构造函数中手动将此数组初始化为全 0:

list = {{{0,0,0},{0,0,0},{0,0,0}},
      {{0,0,0},{0,0,0},{0,0,0}},
      {{0,0,0},{0,0,0},{0,0,0}}};

这使我的程序正常工作,但是,我收到了编译器警告:

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

因此我的问题是

  1. 为什么列表在初始化后有非零条目 标题?
  2. 为什么会收到上述警告信息,如何消除?

我的编译器是 g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2,gcc 版本是 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)

【问题讨论】:

    标签: c++ multidimensional-array g++


    【解决方案1】:

    在 C++03 中,您只能在定义数组时使用该初始化:

    double list[3][3][3] = {{{0,0,0},{0,0,0},{0,0,0}},
                            {{0,0,0},{0,0,0},{0,0,0}},
                            {{0,0,0},{0,0,0},{0,0,0}}};
    

    编译器警告说根据当前标准它不应该接受你的代码,即使它能够通过应用即将到来的标准规则来处理它,其中{...} 被称为 external-initializer。

    在这种特殊情况下,数组是一个成员并且您希望将其初始化为全零,您可以在 C++0x 中使用 value-initialization

    struct test { 
       double list[3][3][3];
       test() : list()
       {}
    };
    

    对于 POD 类型的成员(double 的数组是),初始化列表中的上述语法 (list()) 意味着该成员将被值初始化表示所有值都将设置为 0

    【讨论】:

    • 感谢您的快速回复。很好的解释。
    【解决方案2】:

    我错过了什么吗?或者你不能做吗

    class Class {
    public:
        double array[3][3][3];
    
        Class() : array() { }
    };
    

    【讨论】:

    • @Benjamin 那怎么样,还是漏掉了什么?
    • 类似于大卫的方法,但使用类而不是结构。不过还是有用的。谢谢。
    【解决方案3】:
    1. 在标头中它没有被初始化,它只是被声明了。出于性能原因(与 C++ 中的许多事情一样,初始化是一种选择加入,只有在需要时才付费)。

    2. 该语法仅在初始化数组时有效,而该指令是一个赋值。相反,该语法可以在新的 C++ 标准(以前的 C++0x,现在是 C++11,因为它刚刚获得批准)中的更多地方使用。

    在我看来,解决问题的最快方法就是这样做:

    double * firstElem=&list[0][0][0];
    std::fill(firstElem, firstElem+27, 0.);
    

    list 视为 27 个 doubles 的一维数组并用零填充(有关该技巧的更多信息 here)。

    请注意,此参数也被简单地处理为 array FAQ

    【讨论】:

    • -1。这是错的。你不能像这样使用std::fill来初始化3D数组。
    • @Nawaz:发布答案时我忘记了演员表,现在我添加了它。
    • 即使这也是错误的。事实上,现在更危险了,因为你现在会得到任何警告。它的未定义行为。
    • @David:因为它将 3D 数组视为 1D 数组,这意味着 &firstElem[0] == &list[0][0][0]; &firstElem[1] == &list[0][0][1]; &firstElem[2] == &list[0][0][2] 但据我所知,标准无处保证 &firstElem[3] == &list[0][1][0]。另外,请参阅此主题:stackoverflow.com/questions/2036104/validity-of-the-code
    • @Nawaz:标准保证数组的内容在连续的内存中。它保证&list[1] 在内存中紧随&list[0] 之后,所以是的,它确实保证:(&list[0][0][0] + 4) == &list[0][1][0] 请注意,它们同一对象list 的所有子对象。
    【解决方案4】:

    有一种更简单的方法可以做到这一点。以下应该在 C 或 C++ 中工作,仅用于初始化变量(即不在赋值中):

    double list[3][3][3] = {0};
    

    {0} 是一个特殊的初始化程序,几乎可以将任何结构设置为全零。

    【讨论】:

    • 为了澄清一点,上面的声明意味着“将第一个元素设置为 0。哦,由于我没有指定它们,所以也将所有其余元素设置为零”。我想您可以使用 = {1} 将 list[0][0][0] 设置为 1,并将其余部分设为零,但这不是最清晰的方法。 :)
    • 我猜它会在 main() 中工作,但我不能在标题中使用它。即我会得到这个错误:在“{”令牌之前不允许使用大括号括起来的初始化程序
    • 是的,它只适用于您可以进行初始化的地方。可能静态双重列表......会工作。但是,如果您正在使用 C++,则应该考虑将内容包装在一个类中。全局范围的非类数据只是自找麻烦。
    【解决方案5】:

    为什么不用memset 或循环将值设置为零?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多