问题
The following example initializing a std::array <char, N>
member in a constructor using a string literal doesn't compile on GCC 4.8 but compiles using 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;
}
On first impression it looks like a GCC bug. I feel it should compile as we can initialize a std::array<char, N>
directly with a string literal. For example:
std::array<char, 4> test = {"bug"}; //works
I would be interested to see what the Standard says about this.
回答1:
Yes, your code is valid; this is a bug in gcc.
Here's a simpler program that demonstrates the bug (I've replaced std::array<char, 4>
with S
and got rid of A
, as we can demonstrate the bug just in function return (this makes the analysis simpler, as we don't have to worry about constructor overloading):
struct S { char c[4]; };
S f() { return {"xxx"}; }
Here we have a destination object of type S
that is copy-initialized (8.5p15) from the braced-init-list {"xxx"}
, so the object is list-initialized (8.5p17b1). S
is an aggregate (8.5.1p1) so aggregate initialization is performed (8.5.4p3b1). In aggregate initialization, the member c
is copy-initialized from the corresponding initializer-clause "xxx"
(8.5.1p2). We now return to 8.5p17 with destination object of type char[4]
and initializer the string literal "xxx"
, so 8.5p17b3 refers us to 8.5.2 and the elements of the char
array are initialized by the successive characters of the string (8.5.2p1).
Note that gcc is fine with the copy-initialization S s = {"xxx"};
while breaking on various forms of copy- and direct-initialization; argument passing (including to constructors), function return, and base- and member-initialization:
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"});
The last is particularly interesting as it indicates that this may be related to bug 43453.
来源:https://stackoverflow.com/questions/21555026/initializing-stdarraychar-x-member-in-constructor-using-string-literal-gcc