2
class Test
    {
    public:
        Test(int i) { cout<<"constructor called\n";}
        Test(const Test& t) { cout<<" copy constructor called\n";}
    };
 class Test1
        {
        public:
            Test1(int i) { cout<<"constructor called\n";}
            explicit Test1(const Test1& t) { cout<<" copy constructor called\n";}
        };

    int main()
    {
        Test t(0);  
        Test u = 0;
        //Test1 t1(0);   Line 1
        //Test1 u1 = 0;  Line 2

    }

I observe different outputs. Case 1: When Line 1 and Line 2 are commented the o/p is : constructor called constructor called

Case 2: When Line 1 and Line 2 are uncommented : then compilation error

Can someone explain the outputs and the reason for that. Also can someone tell if operator= actually ends up calling the copy constructor or not.

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Achyuta Aich
  • 85
  • 1
  • 9
  • *"I observe different outputs."* - different to what? Different between runs? *"Can someone explain the outputs"* - why don't you show us the output(s) you've seen so we can be sure we're explaining what you're interested in? *"if operator= actually ends up calling the copy constructor"* - if you put a `cout << "Test u = 0;\n";` just before the `Test u = 0;` line in `mina`, you'll be able to associate the constructor output more reliably with that specific line in `main` and answer the question for yourself.... – Tony Delroy Aug 21 '15 at 04:18
  • What outputs do you observe? (In any case, `operator=` is distinct from the copy constructor and is not used here.) – Brick Aug 21 '15 at 04:19
  • Possible duplicate: http://stackoverflow.com/questions/1051379/is-there-a-difference-in-c-between-copy-initialization-and-direct-initializati – n. m. could be an AI Aug 21 '15 at 04:55
  • 1
    explicit copy ctor is an absurd combination, it serves no useful purpose. – curiousguy Aug 26 '15 at 01:08

2 Answers2

4

Your problem lies in that explicit constructor down there, plus a slight misunderstanding of object initialization.

According to this, the expression:

Type variableName = value;

Will always perform copy initialization of such an object, that means that:

Test1 u1 = 0;

Will effectively call the overloaded constructor Test1::Test1(const Test1&), with argument Test1(int), thus resulting in u1::Test1(Test1(0)).

And, of topping, because you declare the copy constructor as explicit, the copy-style initialization will fail, but this:

Test1 t1(0);

Will compile, because this expression invokes direction initialization, and even if Test1(int) would be marked as explicit, direct initialization is explicit, so every piece matches.

3442
  • 8,248
  • 2
  • 19
  • 41
  • Note that the term *copy initialization* doesn't always mean making a copy or even a move! If `value` already has type `Type`, or a derived class of `Type`, then there is no temporary object, and a constructor is called for `variableName` which takes `value` directly. – M.M Aug 26 '15 at 01:25
  • `Test1 u1(tmp);` doesn't quite capture the essence, because (even if copy elision does not occur), `ui` will be move-constructed from `tmp` if the class has a move constructor – M.M Aug 26 '15 at 01:27
  • @MattMcNabb: Thanks! I'll edit to express that this shall only apply whenever `tmp` in `Test1 u1(tmp)` is an lvalue. But I don't see the point in your first note. Could you please explain it a little better? If I understood correctly, you said that in `Test u1(tmp)` there's no necessarily a temporary, although I don't understand why did you said it, because that's completely irrelevant to my answr. – 3442 Aug 26 '15 at 02:52
  • Huh? In `Test1 tmp(0);`, `tmp` is always lvalue. But that is not related to `Test1 u1 = 0;`. `tmp` is something you made up. I think you are trying to say, in a very convoluted way, that `Test u1 = 0` is the same as `Test u1 = Test(0)` where there is a temporary object `Test(0)`. My first comment is saying that there is no temporary object in some situations. – M.M Aug 26 '15 at 03:40
  • Your new clause "given that `value`..." doesnt make sense, and is a mistake anyway, because `Type variableName = value;` always performs copy-initialization regardless of what `value` is. – M.M Aug 26 '15 at 03:41
  • @MattMcNabb: I tried to make it look good for you according to your points. You're contradicting yourself :). – 3442 Aug 26 '15 at 04:23
  • @MattMcNabb: BTW, read the edit, it does make sense ("Will always perform copy initialization of such an object, given that value is an lvalue, or it's an rvalue binded to a lvalue to const.") – 3442 Aug 26 '15 at 04:23
  • "rvalue binded to a lvalue to const" doesn't make sense. Maybe you meant "rvalue bound to an lvalue reference to const". Even so, it's wrong as my previous comment mentioned. I didn't contradict myself. (Maybe you are under the misapprehension that "copy-initialization" means making a copy, but I tried to clear that up in my first comment) – M.M Aug 26 '15 at 04:26
  • @MattMcNabb: Well, that first thing was actually a typo, and a simple edit will fix it. There's no need for empty "it's wrong" claims. I did never said that "copy initialization" means "calling the copy constructor"/"doing a copy", and so, I did never had such a misconception. Again, this is an empty claim and you're not intending to confuse others/contradict yourself, please be clearer with your comments. – 3442 Aug 26 '15 at 05:04
  • @MattMcNabb: After all, the term "direct initialization" is better suited, as it avoids innecessary confusion (whether the confused one(s) do understand the difference between copy initialization and calling the copy constructor or not), as was clearly stated in my original, unedited answer. – 3442 Aug 26 '15 at 05:07
  • To be clear, my claims are: (1) "Will always perform copy initialization of such an object, given that value is an lvalue, or it's an rvalue binded to a lvalue reference to const." is wrong, and ""Will always perform copy initialization of such an object." is correct ; (2) The code `Test1 tmp(0); Test1 u1(tmp);` is significantly different to `Test1 u1 = 0;` (what does "pseudo-evaluates" even mean?) – M.M Aug 26 '15 at 05:17
  • This is one of the top reasons the C++ standard people are a lot of dumbs who don't understand why would people (unlike computers) forget something if they're given too much information that can't be deduced off by other simpler rules. Anyway, now that I read my answer, I think that I messed up a bit the stuff meanwhile doing the edits, and in effect it (now) doesn't makes any sense. I'll undo all the edits and take this conversation as finalized; it's not producting anything useful for anyone. **Edit**: Just in case, I'll remove the "pseudo-evaluates to" stuff; it's innecessary. – 3442 Aug 26 '15 at 05:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/87946/discussion-between-kemyland-and-matt-mcnabb). – 3442 Aug 26 '15 at 05:35
0

Test u = 0 is case of converting constructor. Please refer to What is a converting constructor in C++ ? What is it for? for detail .
I tried compiling commented lines after removing the comment and it compiled for me. I am using gcc version 4.3.4. Which version of compiler are you using ?

Community
  • 1
  • 1
user258367
  • 3,247
  • 2
  • 18
  • 17