10

以下示例std::array <char, N>使用字符串文字初始化构造函数中的成员不会在 GCC 4.8 上编译,但使用 Clang 3.4 编译。

#include <iostream>
#include <array>

struct A {
  std::array<char, 4> x; 
  A(std::array<char, 4> arr) : x(arr) {}
};


int main() {
    // works with Clang 3.4, error in GCC 4.8.
    // It should be the equivalent of "A a ({'b','u','g','\0'});"
    A a ({"bug"});
    for (std::size_t i = 0; i < a.x.size(); ++i)
        std::cout << a.x[i] << '\n';

    return 0;
}

在第一印象中,它看起来像一个 GCC 错误。我觉得它应该编译,因为我们可以std::array<char, N>直接用字符串初始化 a 。例如:

std::array<char, 4> test = {"bug"}; //works

我很想看看标准对此有何评论。

4

1 回答 1

2

是的,您的代码是有效的;这是 gcc 中的一个错误。

这是一个演示错误的更简单的程序(我已经替换std::array<char, 4>S摆脱了A,因为我们可以仅在函数返回中演示错误(这使分析更简单,因为我们不必担心构造函数重载):

struct S { char c[4]; };
S f() { return {"xxx"}; }

这里我们有一个类型的目标对象,S它是从花括号初始化列表中复制初始化的(8.5p15),因此该对象是列表初始化的(8.5p17b1)。 是一个聚合 (8.5.1p1),因此执行聚合初始化 (8.5.4p3b1)。在聚合初始化中,成员从相应的初始化子句(8.5.1p2)复制初始化。我们现在返回 8.5p17,目标对象的类型和初始化字符串字面量,因此 8.5p17b3 将我们指向 8.5.2,并且数组的元素由字符串的连续字符(8.5.2p1)初始化。 {"xxx"}Sc "xxx"char[4]"xxx"char

请注意,gcc 可以很好地进行复制初始化S s = {"xxx"};,同时打破各种形式的复制和直接初始化;参数传递(包括到构造函数)、函数返回以及基和成员初始化:

struct S { char c[4]; };
S f() { return {"xxx"}; }
void g(S) { g({"xxx"}); }
auto p = new S({"xxx"});
struct T { S s; T(): s({"xxx"}) {} };
struct U: S { U(): S({"xxx"}) {} };
S s({"xxx"});

最后一个特别有趣,因为它表明这可能与错误 43453有关。

于 2014-02-04T16:53:03.857 回答