12

In this book I am currently reading I ran across this:

A class doesn't need a constructor. A default constructor is not needed if the object doesn't need initialization.

Am I correct in inferring from the above that the compiler does not generate a default constructor for the class/structure in some cases? If yes, what are those cases? I will venture and say POD is probably one. Are there any other?

EDIT: I have changed the title as the original title gave the meaning that I asked when was a default constructor not defined instead of asking when does a class not have a constructor at all.

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
Samaursa
  • 16,527
  • 21
  • 89
  • 160
  • 6
    Note that "default constructor" is not a synonym for "compiler-generated constructor". – Oliver Charlesworth Aug 20 '11 at 13:23
  • A default constructor is always generated, but it is not always called. Consider a local variable that is not const, is of POD type, and is declared without an initializer. The object is cobbled up from memory. Even though the default constructor does exist, it is not called to construct the object. The data members have indeterminate value. – David Hammen Aug 20 '11 at 15:17

9 Answers9

10

A class doesn't need a constructor. A default constructor is not needed if the object doesn't need initialization.

I think the author is talking about this situation:

some_type some_function () {
   POD_type this_is_intentionally_uninitialized;
   ...
}

Under some circumstances a constructor won't be called, period. As soon as you write a constructor you don't have a POD class, so now the constructor will be called.

Whether it is a good or bad thing to have an object running around that contains random, uninitialized data is a different question entirely.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • 2
    Hmm, that is exactly what I was asking about. Could you confirm what you said `"Under some circumstances a constructor won't be called, period"` by a citation (the standard or maybe disassemble). I will then mark this as the answer instead (+1) – Samaursa Aug 21 '11 at 23:34
  • And just to make sure I understood correctly... the `POD_type` you declared can be used (by calling `POD_type.someVar`), but its members are not initialized because there are no member functions (constructors or otherwise)... correct? – Samaursa Aug 21 '11 at 23:38
  • 4
    @Samaursa: ISO/IEC 14882:2003(E) section 8.5 paragraph 9 (emphasis mine): "If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. **Otherwise, if no initializer is specified for a non- static object, the object and its subobjects, if any, have an indeterminate initial value**" – David Hammen Aug 21 '11 at 23:50
6

A default constructor is always declared. But it is not always defined. Only if it is used, then the compiler (or you) define it. Examples:

struct A { std::string str; };
// not yet defined

struct B : A { };
// not yet defined

B b; 
// Now B::B and A::A are defined

Note that this has direct practical consequences

struct A { private: A(); };
struct B : A { };
// valid, as B::B is not yet defined

B b; 
// now invalid, because B::B is defined and tries to call a 
// private base class constructor
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • So as soon as you instantiate the object, a constructor is defined and called? What about pure C structures? If I have `typedef struct A { int a; }A;`, then typing `A a;` does not generate a constructor does it (I thought that was the definition of a POD structure)? Why is it different in the above example? Is it simply because we are now dealing with C++? – Samaursa Aug 20 '11 at 22:14
  • The compiler always generates a default constructor for a POD class. It does not always use it. – David Hammen Aug 20 '11 at 22:54
  • @DavidHammen: What do you mean by "generates"? A default constructor is implicitly declared only if a class has no user-declared constructors and it is only defined if it is used. – CB Bailey Aug 20 '11 at 23:20
  • @Charles: The only objects that are not initialized via a constructor are POD objects. The presence of a user-declared constructor means the class is not POD. The compiler always implicitly declares a default constructor when the class is defined. Whether the compiler defines that default constructor at that time is up to the implementation. In any case, you guys are missing the point here, which is embodied in the words *if the object doesn't need initialization*. Non-POD objects are always initialized. – David Hammen Aug 21 '11 at 00:13
  • @DavidHammen: The first sentence of your comment is not true. Some non-POD objects of class type may initialized other that via a constructor too. For example a class without any user-declared constructors may be value-initialized even if it is not POD and aggregate classes may be initialized with a brace enclose initializer clause which also doesn't use a constructor even if the aggregate class is non-POD. Also, implementations are not allowed to define an implicitly declared default constructor unless it is used which will happen for default initialized objects of non-POD class type. – CB Bailey Aug 21 '11 at 07:09
  • @Samaursa theoretically, in C++03 it does not generate a constructor for your `A a;`, because it does not call a constructor in the first place. But in C++0x it does generate a constructor and calls it. The end result however is the same. The specification in C++0x is simplier and has less special cases. You as a user won't notice the difference, though. – Johannes Schaub - litb Aug 21 '11 at 09:16
  • @Johanes: The context of the quoted text is a book on optimization. Bypassing initialization is one of the tricks some people use to shave CPU cycles. There's no reason to bother with initialization if subsequent code will later set every element of the contents of the object in question and unset elements are not accessed in the interim. – David Hammen Aug 21 '11 at 10:18
  • @David I have no idea why you are telling me this. It doesn't seem to be an answer or comment to any comment I made or to the answer I made. Can you please elaborate? – Johannes Schaub - litb Aug 21 '11 at 11:34
  • @Johannes: Elaboration: Your answer is not an answer to the OP's question. The OP wasn't quite clear with regard to context, but the linked e-book is very clear. The phrase "A default constructor is not needed if the object doesn't need initialization" is made with regard to optimization. The goal is to avoid calling any constructor. Some constructor will be called if you declare any constructor for a class and then declare a variable of that class. Most of the answers have been about what happens if you declare a constructor. The correct answer in this context is not to declare a constructor. – David Hammen Aug 21 '11 at 18:32
  • @David Hammen: when it comes to C++, a random e-book does not trump the ISO C++ Standard. And a book that fails to make the distinction between declarations and definitions should be considered even less authoritive. – MSalters Aug 22 '11 at 09:36
  • You are missing the point. The author of that e-book is taking advantage of how C++03 works. No constructor will be called for an instantiation of a POD class that is non-global, non-const, is declared without an initializer list. There is a performance penalty in initializing an object. Avoiding that performance penalty is a (small) optimization hack. I tend to go the other extreme: Always declare a constructor and always make sure each member is initialized. I don't like uninitialized data running around my programs. – David Hammen Aug 22 '11 at 12:23
  • @MSalters: I agree with your point `when it comes to C++, a random e-book does not trump the ISO C++ Standard`. My question sparked from the notion of POD. Since C does not have the notion of Ctors/Dtors (hence workarounds like http://stackoverflow.com/questions/537244/constructor-in-c/537267#537267) I guessed that in C++ a structure that is a POD would not get a Ctor/Dtor because it is costly (even if it is a minor cost - I have read time and time again, in C/C++ you don't pay for what you don't use [e.g. pointers not initalized to NULL automatically]) and hence the question. – Samaursa Aug 22 '11 at 22:59
  • @Samaursa: With modern compilers, the cost is literally _zero_. Not a single instruction is added to your code. – MSalters Aug 23 '11 at 08:32
  • @MSalters: Not saying I don't believe you, but any proof to back it up would be great! And just because a compiler does everything for me does not mean I should not know about it at all. I am curious and yes it is related to optimization but that does not mean I should automatically not know about it because `compilers are so good`. – Samaursa Aug 23 '11 at 13:29
  • @Samaursa: Essentially the default ctor is inline-able, and doesn't touch members. As a result, zero instructions are inlined. Proof is easy: just check the output of your favorite compiler. – MSalters Aug 23 '11 at 14:23
  • @MSalters: Fair enough, I will try that at the first possible chance. Btw, I am assuming that it is inlined only when optimizations are turned on, correct? Potentially, you could shave off time (however small) from the debug build, yes? – Samaursa Aug 24 '11 at 13:21
4

If you always create objects of an class using a constructor with parameters it won't need the default constructor.

The compiler generates a default constructor for every class, but if you define your own constructor for that class then the compiler does not generate a default constructor by itself. As long as you create objects of such an class through the constructor you provided, the class won't need and have a default constructor.

class Myclass
{
    int m_i;
    public:
        Myclass(int i)
        {
            m_i = i;
        }

};

int main()
{
    Myclass obj1(10); // #1, uses overloaded constructor
    Myclass obj2; //#2, Will generate compiler error of no matching constructor
    return 0;
}

In context of the above example, consider the quote from the book:

A class doesn't need a constructor. A default constructor is not needed if the object doesn't need initialization.

In the above example as long as the object of Myclass is created in using #1, the class does not require and have a default constructor.

The default constructor needs to be defined for the class, if object of Myclass is created in a way which needs the default constructor, i.e: #2.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • My title should have been "In what cases is there is no constructor at all, even a default constructor" – Samaursa Aug 20 '11 at 22:11
  • 1
    @Samaursa: The only time there isn't a constructor of any sort is when you have declared some constructor but have not provided an implementation. The result is an unusable class. If on the other hand you don't declare any constructor, the compiler will (must!) create a default constructor on your behalf. This is what happens with a POD class. In the case of a POD class, that automatically-generated constructor is not called under certain circumstances. See my answer for details. – David Hammen Aug 20 '11 at 22:52
1

So simply put - (in context of CPP) If not Constructor is defined, then compiler doesnt have default constructor. It is defined by the compiler only if it is required.

There are certain cases where it is being done by the compiler. Some of which are -

  1. When we have a class which has a base class object as member( and derived class constructor is not defined). In this case the default contructor for derived class is created because the prolog of its contructor needs to call the base class contructor.
  2. We have a container object. Below code explains this.

    class Legs
    {
    ctor(); // ctor stands for constructor
    };
    class cat
    {
    Legs leg;
    public:
    cat(){}
    };
    
  3. In case of Virtual functions, the setting of Virtual table pointer to the correct V-Table is done in Constructor. For this reason also, the default constructor will be defined by the compiler.

0

A default constructor is not defined for a class if another constructor is declared.

For POD types (in the sense of being both trivial and standard-layout, as those terms are defined in C++11) it is a moot point whether the compiler generates a constructor or not, since the compiler-generated constructors are trivial. For gory details, have a look at What are Aggregates and PODs and how/why are they special?

Community
  • 1
  • 1
Peter
  • 35,646
  • 4
  • 32
  • 74
0

In my opinion, that sentence means that you don't always have to write your own default constructor, since some classes may not need to be initialized by default.

For example, if your class contains several class fields that provide their own default constructor you don't need to write any default constructor, since the members' constructor is called anyway by default.

At the extreme opposite, you may want to write a struct or a class of PODs for which you rely on the programmer to initialize correctly its fields manually; in this case, you may not write a default constructor, so the compiler will write its own that will leave these fields to their default uninitialized values (actually, it will be a no-op, and will probably be optimized away).

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
0

The compiler only declares and defines an automatically generated default constructor if you haven't provided any constructor.

With a non-instantiable parent class however, it is possible to prevent any kind of constructor from working. By adding a dummy constructor with a dummy parameter, it is possible to kill only the automatically generated default constructor, at the expense of more red tape.

Frigo
  • 1,709
  • 1
  • 14
  • 32
0

There's certain ambiguity in your question. You see, the implicit actions that the compiler takes with regard to constructors involve both declaring them and defining them. If some constructor is declared but not defined, do you consider it exists or not?

Anyway, there's no way to create a class that has no constructors declared for it. The copy constructor, for one example, is always declared. There's no way to suppress it. If you don't declare it yourself, the compiler will declare it for you.

As for the default constructor - it is possible to suppress its implicit declaration. If you declare any constructor yourself (i.e. explicitly), the compiler will not implicitly declare the default one. But in this case your class will, of course, have a constructor: the one that you declared yourself. (Plus, as I said above, the copy constructor is always declared).

As for implicitly defined constructors... They are defined by the compiler only if you use them. And, of course, they are defined only if it is possible. (If you use an implicit constructor, and it proves to be impossible to define, then your program simply will not compile).

So, once again, when it comes to declared constructors, it is not possible to have a class with no constructors at all. Any class has at least one constructor declared for it.

If your are interested in defined constructors specifically, then it is indeed possible to have a class, for which no constructor is defined. Here's an example for you

struct S {
  S(const S&);
};

That's it. The class has one constructor declared it in, but it is not defined :)

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • The question pertains to classes for which *no* constructor is invoked when an instance of that class is created. The constructor is not called for non-global, non-const variables of a POD type that are declared without an initializer list. The initial contents of such an object are indeterminate. If you declare a constructor you no longer have a POD class, so your example is not what the OP asked about (and it certainly isn't what the author of that e-book linked to in the OP was writing about). – David Hammen Aug 20 '11 at 23:29
-1

some_type some_function () { POD_type this_is_intentionally_uninitialized; ... }

Avinash
  • 361
  • 4
  • 16