9

From C++11 Standard § 8.5 p6 we have:

If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.

The following code should not compile. But it does, both in Coliru and Ideone.

class A{};

int main() {
    const A a;
}

Edit:

While trying to understand what's going on here, I ended up with the following code, which compiles (at least it's compliant with the Standard, as A has a user-provided constructor). But then the following question came to my mind: which Standard clause does guarantee that a.b.j is initialized with 0 (see the code in Ideone), below?

#include <iostream>
struct B { int j; B(){ std::cout << "B()" << '\n'; } };
struct A
{
    struct B b;
    int i;

    public:
    A(): i(1) { std::cout << "A()" << '\n'; }

};  

int main() {
    const A a;
    std::cout << a.b.j << '\n';
    std::cout << a.i << '\n';
}

Edit1:

Sorry for the Edit above, but I'm still not used with Unixes. Last week Dietmar Kühl called my attention to the fact that "Most UNIXes start off with zero initialized pages". Therefore, a.b.j is not 0 because of initialization, as I was thinking. As a matter of fact, I've just compiled the code with VS2010, and the result for a.b.j was an unitialized value, as expected. So, the question in Edit should be disregarded.

But I'm curious to know whether clang++ or g++ would also show an error for this second snippet. Thanks.

Community
  • 1
  • 1
Wake up Brazil
  • 3,421
  • 12
  • 19
  • 7
    clang++3.4 *error: default initialization of an object of const type 'const A' requires a user-provided default constructor* – dyp Jan 03 '14 at 17:55
  • @DyP Yup, for me too. And g++ says: `error: uninitialized const ‘a’` –  Jan 03 '14 at 17:56
  • @DyP I've never seen such simple code fail like that. o_0 – David G Jan 03 '14 at 17:59
  • @0x499602D2 Well I'd certainly expect `const int i;` to not compile, this is quite similar. – dyp Jan 03 '14 at 18:05
  • 1
    Note that once you add a data member, g++ complains: `main.cpp:7:13: error: uninitialized const 'a' [-fpermissive] main.cpp:1:8: note: 'const struct A' has no user-provided default constructor` – dyp Jan 03 '14 at 18:14
  • I would answer "yes, that should be an error", but first I'd have to prove that no clause in the standard adds an exception to the above rule, which is tricky. – Yakk - Adam Nevraumont Jan 03 '14 at 19:35
  • 1
    possible duplicate of [Why does C++ require a user-provided default constructor to default-construct a const object?](http://stackoverflow.com/questions/7411515/why-does-c-require-a-user-provided-default-constructor-to-default-construct-a) – TemplateRex Jan 03 '14 at 19:53
  • @DyP See my 'Edit' above. – Wake up Brazil Jan 04 '14 at 13:39
  • @WakeupBrazil Your 'Edit' might even be another question. The answer is: none (AFAIK). That's why you have to supply a user-defined ctor, and that's why if this ctor was marked `constexpr`, it'd be ill-formed. `a` is default-initialized, which default-initializes `a.b` according to [class.base.init]/8. This leads to `B`'s default ctor being called, which default-initializes `a.b.j` (= no init of `j`) – dyp Jan 04 '14 at 13:51
  • 1
    @TemplateRex i disagree. the other question asks for the reason of that rule. this question asks whether and why compilers don't follow that rule for empty classes. – Johannes Schaub - litb Jan 04 '14 at 14:21
  • @JohannesSchaub-litb But and empty class does not have a user-provided default constructor, or does it? – TemplateRex Jan 04 '14 at 16:10
  • @DyP Thanks for your input. See my 'Edit1' above. – Wake up Brazil Jan 04 '14 at 17:40

2 Answers2

4

Having studied the rules for initialisation and aggregates, I conclude that you're right — this is technically ill-formed.

Your compiler is taking a shortcut because there are no members and thus no initialisation is practically required. (Funnily enough, the ancient GCC 4.1.2 rejects the program.)

Unfortunately I have nothing to quote because there is simply no rule overriding [C++11: 8.5/6] for this case.

As for why the standard doesn't allow this, well why should it? Empty classes are of next to no use, I can't see a reason to bother with actively writing an exemption to the wider, more useful rule for this edge case.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
1

Taking into account a note in paragraph #2 of section 7.1.6.1 The cv-qualifiers where there is written:

2 [ Note: Declaring a variable const can affect its linkage (7.1.1) and its usability in constant expressions (5.19). As described in 8.5, the definition of an object or subobject of const-qualified type must specify an initializer or be subject to default-initialization. —end note ]

it seems that indeed the compilers bahave oddly.

Though if you will add a data member the code will not be compiled in ideone but will be compiled at least in MS VC++ 2010. In the quote you presented there is nothing said about data members.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335