34

This is very trivial, but Czech language (my native) doesn't distinguish between implicit and default, so I am confused by some Czech translations what is the difference between implicit and default constructor or constructor call.

struct Test {
  Test(int n=0) { }
};

Can you describe in these terms what is:

  1. Test t1;
  2. Test t2();
  3. Test t3 = 3;
  4. Test t4(4);
  5. Test t5 = Test(5);

?

Jan Turoň
  • 31,451
  • 23
  • 125
  • 169
  • 4
    I would recommend that you use C++ (technical books in general) in english when possible. – David Rodríguez - dribeas Sep 09 '12 at 19:17
  • 8
    I do. The problem is, that my native language confuses *implicit* and *default* in my mind, it is mostly linguistic issue. Besides the coding skills I need to change the language of thinking too - which is quite exciting challenge. – Jan Turoň Sep 09 '12 at 19:26
  • 1
    I doubt that the translation is the same since the meaning is quite different in English. Default is often translated as _výchozí_, while implicit as _implicitní_ meaning something like _nevýslovný_. (disclaimer: I know Czech only a little) – Roman Shapovalov Feb 16 '16 at 10:27
  • @RomanShapovalov that could be exact translation, but *nevyslovený* has also other misleading meanings in Czech, so it's often translated semantically or (perharps better) not at all. – Jan Turoň Feb 16 '16 at 10:35
  • 1
    The English words "implicit" and "default" do not cleanly describe the natures of these constructors. These words are labels, and as programmers we must learn what actual C++ behavior they correspond to. If the designers of C++ had assigned these words the other way around, our job would not have been much different. – Beta Jul 27 '20 at 02:45

2 Answers2

46

The terms default and implicit, when talking about a constructor have the following meaning:

  • default constructor is a constructor that can be called with no arguments. It either takes no arguments or has default values for each of the arguments taken.

  • implicit constructor is a term commonly used to talk about two different concepts in the language, the

    • implicitly declared constructor which is a default or copy constructor that will be declared for all user classes if no user defined constructor is provided (default) or no copy constructor is provided (copy). That is, a class with no constructors declared by the user has one default constructor implicitly declared.

    • implicitly defined constructor is a implicitly declared constructor that is used (odr-used1 in the language and for which the compiler will provide a definition.

     

    struct test
    {
        test(int i = 0) { }
        // test(test const&) implicitly declared here
    };
    
    struct test2 { };      // implicitly declared: test2(), test2(test2 const&)
    
    int main()
    {
        test t;
    
        test copy(t);      // causes *definition* of the implicitly
                           // declared copy constructor
    
        test2 t2;          // causes *definition* of test2::test2()
    
        test2 copy2(t2);   // causes *definition* of test2::test2(test2 const&)
    }
    

In simple terms, a constructor is default if it can be called with no arguments. A constructor is implicit(ly declared/defined) if it is not provided by the user but declared/defined.

As of the specific cases:

Test t1;

Uses the default constructor, Test(int = 0), which is not implicit.

Test t2();

This is a strange quirk of the language, it declares a function that takes no arguments and returns a Test object.

Test t3 = 3;

This is called copy-initialization and is equivalent to the composition of an implicit* conversion from 3 to Test and copy construction of t3 from the result of the conversion. This will use the Test(int) constructor for the conversion, and then the implicitly defined (and declared) copy constructor. Note: the compiler can optimize away the copy, but it must verify that the copy constructor is available (access specifiers) and can be defined.

Test t4(4);

Uses the Test(int) constructor, which in this case is not acting as a default constructor.

Test t5 = Test(5);

Equivalent to the Test t3 = 3 case, with the only difference that the conversion from 5 to Test is explicit in this case. In this example it won't matter, but if the constructor had been marked as explicit this line would compile while the t3 case would fail.


*) Yet another use of implicit, in this case referring to the fact that the conversion from 3 to Test is not explicitly requested in the code. Compare this with t5 where the conversion is explicitly requested by the programmer: Test(5).

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • 1
    @Leonid: the term is formally defined in the standard, but in effect it means that something calls it or otherwise requires it to exist. – Steve Jessop Sep 09 '12 at 17:30
  • And then, as if there weren't enough implicit constructors, we also have aggregate initialization for aggregate types :-) https://stackoverflow.com/questions/17712872/what-is-aggregate-initialization – Ciro Santilli OurBigBook.com Nov 13 '18 at 19:21
5

You seem to be confusing some of the terms. A default constructor is one which takes no parameters, an implicit call is when you directly call the constructor.

Anyway:

1) Test t1;

Default constructor.

2) Test t2();

Function declaration.

3) Test t3 = 3;

Copy initialization. Will call the conversion constructor, create a temporary Test from 3, and use the copy constructor to create t3.

4) Test t4(4);

Direct initialization. Uses the conversion constructor directly.

5) Test t5 = Test(5);

Copy initialization. Similar to 3).

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • Which of 1-5 is implicit call then? – Jan Turoň Sep 09 '12 at 15:20
  • @JanTuroň I'd say 1) and 3). Note that 2) doesn't call the constructor at all. – Luchian Grigore Sep 09 '12 at 15:22
  • C++ Primer Plus Czech edition claims that 4) is implicit call. Is it translation error? – Jan Turoň Sep 09 '12 at 15:27
  • @JanTuroň could be (and seems like a mistake), but how is implicit/explicit defined? In 4), to me it looks like you're *expplicitly* calling `Test(int)`. – Luchian Grigore Sep 09 '12 at 15:30
  • I am not sure. The book says that 4) is implicit call, 5) is explicit call and there is nothing about 1) and 3). 5) is definitely explicit. I've seen on multiple places 1) and 3) reffered as implicit. But I am still confused about 4) – Jan Turoň Sep 09 '12 at 15:38
  • 1
    @JanTuroň nonetheless, implicit & explicit are, in this case, use informally, so it largely depends on what the authors mean by the terms. – Luchian Grigore Sep 09 '12 at 15:40
  • Surely the fifth and third would be *move* initialization now, since `Test(5)` is an rvalue. – Puppy Sep 09 '12 at 16:30
  • @DeadMG: Not according to the language specification... §8.5/13 *The initialization that occurs in the form `T x=a;` [...] is called **copy-initialization*** – David Rodríguez - dribeas Sep 09 '12 at 19:14
  • It might be named that, but I think that it's still a misnomer when moving might be the Standard-mandated result. – Puppy Sep 10 '12 at 23:46