10

Consider the given code

struct ABC
{
    ABC()
    {
        std::cout<<" Calling from default constructor";
    }

    ABC(const ABC &copy)
    {
        std::cout<<"Calling from copy constructor";
    }
};

int main()
{
    ABC abc = ABC();
}

I have two questions


Q1) Removing const from the copy constructor parameter declaration gives error. Why?

Q2) After adding the const keyword I dont see a call to the copy constructor. Why? The copy constructor does not get called so why is the const necessary?


TIA

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
Ram Gandhi
  • 101
  • 2
  • I'd add Q3) Why there's nothing displayed after we change that line to `ABC abc(ABC());` ? – Kos Nov 27 '10 at 14:15
  • 2
    Answer to (Q3) [here](http://stackoverflow.com/questions/4283576/constructor-invocation-mechanism/4283589#4283589). Answers to Q1 and Q2 [here](http://stackoverflow.com/questions/4286301/why-isnt-the-copy-constructor-called-here/4286330#4286330) – Prasoon Saurav Nov 27 '10 at 14:17
  • @Prasoon: Q1 is not answered in the link you posted. – Yakov Galka Nov 27 '10 at 14:30
  • @ybungalobill : The answer to Q1 is that temporaries in C++ cannot be bound to non-constant references. The code would be ill-formed without the `const`. – Prasoon Saurav Nov 27 '10 at 14:32
  • Oh please, do search the site before posting, this one has been getting rehashed so often.... – Matthieu M. Nov 27 '10 at 15:48

4 Answers4

5
  1. You need the const because you try to initialize abc with a temporary ABC() which is const. Hence if the constructor is not const the compiler must reject the code.

  2. After you make it const the code is standard complaint and the compiler can compile it. However it's allowed to optimize out the copy in this case as said in the standard, so it removes the call to the copy constructor.

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • @ybungalobill: The compiler does not generate copy constructors in all scenarios, even if you don't explicitly write one that matches the signature exactly. I can't remember the rules, but they're not always generated. – Puppy Nov 27 '10 at 14:31
  • @DeadMG: Who said that they are always generated? Really? What's the connection? They are not generated when they can't be generated (like when you have base classes or members without copy constructor, etc...). The copy constructor is generated in this example. – Yakov Galka Nov 27 '10 at 14:37
  • 2
    You are mistaken about the default copy constructor: "A non-template constructor for class `X` is a copy constructor if its first parameter is of type `X&`, `const X&`, `volatile X&` or `const volatile X&`, and either there are no other parameters or else all other parameters have default arguments" – UncleBens Nov 27 '10 at 15:35
  • 2
    And if the code compiles for you, then you are probably using VC++, which allows binding temporaries to non-const references as a nonstandard extension. Compilers which find error with this code are correct as far as the language specification goes. – UncleBens Nov 27 '10 at 15:37
  • @UncleBens: OK, but does it mean that it prevents the creation of default copy constructor with a `const X&` parameter? – Yakov Galka Nov 27 '10 at 16:10
  • 2
    Temporary `ABC()` is *not* const. It is a temporary. That alone answers the first question. In C++ it is illegal to bind non-const references to temporaries. – AnT stands with Russia Nov 27 '10 at 16:16
  • A class only has an implicitly generated copy constructor if no user-defined one exist. BTW, the implicit copy constructor will usually be `X(const X&)` except when bases or members don't have a const-reference copy constructor in which case it will be `X(X&)` – UncleBens Nov 27 '10 at 17:18
3

Q1) Removing const from the copy constructor parameter declaration gives error. Why?

ABC abc = ABC();

is equivalent to

ABC abc((ABC()));

Since you are passing a temporary to the copy constructor, it can only bind to const references, not non-const references.

A copy constructor can take non-const references (e.g std::auto_ptr), but this means their usage is more restricted.

Q2) After adding the const keyword I dont see a call to the copy constructor. Why? The copy constructor does not get called so why is the const necessary?

In the given scenario the compiler is allowed to optimize redundant calls to constructor away. Why create a default object only to copy it, if it could just invoke the default constructor alone?

However, even if calls to copy constructor are optimized away, the compiler has to check that the code would be valid as written - as if the copy construction was not optimized away.

UncleBens
  • 40,819
  • 6
  • 57
  • 90
2

The const is necessary since you are not allowed to bind a temporary to a non-const reference. Even though the compiler optimizes away the copy constructor, that is not until a latter stage.

The C++ 0x standard is addressing this with the addition of rvalue references. which would allow you to drop the const parameter to a non-const...

ABC( ABC&& copy) 

Although you would still want the regular reference copy constructor...

diverscuba23
  • 2,165
  • 18
  • 32
  • +1 for mentioning that; That's called the "move constructor", I suppose? – Kos Nov 27 '10 at 15:26
  • @kos: often times yes, but nothing says that it has to follow move semantics (i.e. leave the original object in a default constructed state), so if you just want copy semantics for temporaries, then this works well too. – diverscuba23 Nov 27 '10 at 15:30
1

If you also define the assignment operator you'll see that not even that one gets called: compiler optimizes ABC abc = ABC(); in ABC abc;, since they've got the same semantics.

About the other doubt, G++ doesn't complain about declaring copy constructor parameter as non-const (not even with -Wall -W -std=c++98). Didn't check out the standard about this anyway.

peoro
  • 25,562
  • 20
  • 98
  • 150
  • You forgot `--pedantic`, but also doesn't change a thing. But not surprising really - why not allow to have a copy constructor only for non-const objects in some cases? Or different copy constructors for const and non-const? – Kos Nov 27 '10 at 14:37