0

As a student , I was testing out various ways of invoking the copy constructor . I came across 3 of them :

Test t2 = t1 // 1 ; 
Test t3(t1) // 2 ; 
Test t4 ;  // 3 ;
t4 = t1 ;

The explicitly defined copy constructor adds 10 to each of the data members of t1 . The first 2 work fine and call the explicit one . However the 3rd approach calls the implicit copy constructor i.e. there is no addition of 10 taking place .

My code :

#include <iostream>
using namespace std ; 
class Test
{
    int m,n ; 
    public: 
    Test() ; 
    Test(int,int) ; 
    ~Test() ; 
    Test(Test&) ; 
    void showData() ; 
}; 
inline Test::Test(Test& t)
{
    cout<<"called"<<endl ;
    m = t.m + 10 ; 
    n = t.n + 10 ; 
}
inline Test::Test(){}
inline Test::Test(int m,int n)
{
    Test::m = m ; 
    Test::n = n ; 
}
inline Test::~Test(){}
inline void Test::showData()
{
    cout<<m<<" "<<n<<endl ; 
}
int main()
{
    Test t1(3,4) ; 
    t1.showData() ; 
    Test t2(t1) ; 
    t2.showData() ;
    Test t3 = t1 ;
    t3.showData() ;
    Test t4 ; //calls the implicit one 
    t4 = t1 ; 
    t4.showData() ;
    return 0 ; 
}

Output :

3 4
called
13 14
called
13 14
3 4

I tried overloading the assignment(=) operator to manually solve the problem with the 3rd approach which did work , but I want to know why the 3rd approach calls the implicit copy constructor even though an definition has been provided explicitly .

4
  • The explicitly defined copy constructor adds 10 to each of the data members of t1 -- Please don't do anything like this in real code. One of hardest to find bugs are copy constructors that don't actually make a copy of the passed-in object. Also, you should be outputting the value of this, not just "called". That way you know exactly what object(s) are being created, copied, and destroyed (your destructor doesn't output any information). Commented May 7, 2024 at 21:33
  • @PaulMcKenzie Looks like a reasonable way to make a test case to learn how things work to me. Most people will just stick cout statements in their code, but this works too. From OP’s language and comprehensive test it sounds to me like he has a pretty good grasp on what a copy constructor should actually do. Commented May 7, 2024 at 21:36
  • 1
    "The first 2 work fine and call the explicit [copy constructor] . However the 3rd approach calls the implicit copy constructor" - There is only 1 copy constructor. Either you define it yourself, or you let the compiler define it for you. You can't have both. The 3rd approach is not calling any copy constructor, though. Commented May 7, 2024 at 21:48
  • 1
    See this. That code tracks the objects being created, copied, and destroyed. Commented May 7, 2024 at 22:07

1 Answer 1

5

These invoke a copy constructor:

Test t2 = t1;  // calls Test::Test(const Test& t)
Test t3(t1);   // also calls Test::Test(const Test& t)

While this invokes a copy assignment operator:

Test t4 ;  // calls Test() constructor
t4 = t1 ;  // calls Test& operator=(const Test& t)

Both the copy constructor and the copy assignment operator will have a default implementation created by the compiler if you don't define one yourself.

Having the const Test& as a parameter allows you to invoke it on const objects. Your code without the const won't compile with const Test t1;.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.