copy constructor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
using namespace std;
class sample
{
public:
    int i;
    sample(int ii = 0)
    {
        i = ii;
    }
    sample(const sample &s)
    {
        this->i = s.i;
        cout << "copy constructor" << endl;
    }
    sample operator=(const sample &s)
    {
        this->i = s.i;
        cout << "assignment operator" << endl;
    }
    sample fun(sample s)//copy constructor called
    {
        sample t;
        t = s;//assginment operator called
        return t;
    }
};
int main()
{
    sample s1(5), s2(10);
    sample s3 = s1.fun(s2);
    return 0;
}

When above program is run output is shown below:
copy constructor
assignment operator


My confusion is, why copy constructor is not called when return value of s1.fun is used to initialize s3 object in main function.
Last edited on
You forgot the return statement in your assignment operator.
Last edited on
You do need to return *this from the assignment operator, and I'm surprised your code even compiled with that error, but I don't think that's relevant to your question. I think the reason why the copy constructor is not called is because it needs an actual object to copy from. Notice how its input parameters are passed by reference. The fun function returns by value, which means s3 is set equal to that value instead of an object that has that value.

My follow up question then is what is called in the declaration of s3, because that doesn't fit requirements for the default or copy constructors or the assignment operator.
Last edited on
I think one possible answer to my question is that something like that shouldn't ever happen because if a class that has the copy constructor or assignment operator overloaded is returned in a function, it should be returned by reference instead of by value to prevent a straight value by value copy (a shallow copy) being returned.

So am I correct to say that returning an object (that has the copy constructor overloaded) by value doesn't call the copy constructor of that object and instead just makes a shallow copy? I've never heard of it calling the copy constructor for a return value but I would think that would make sense, like in these types of cases.

I also think you should keep in mind that the copy constructor and assignment operator are not needed. I understand that you may be just doing this for practice with them but it's good to know that they are only really supposed to be used if the class somehow manages dynamic memory. This class does not, so in this case a shallow copy would be the same as a copy constructor or assignment operator overloaded copy.
why copy constructor is not called when return value of s1.fun is used to initialize s3 object in main function.

Because C++ does not require it to be called. Since about 1992, we had an optimization called "named return value optimization":

Relevant part of your code:
1
2
3
4
5
6
7
sample fun(sample s)
{
      sample t;
      t = s;
      return t;
}
sample s3 = s1.fun(s2);


rule (from http://en.cppreference.com/w/cpp/language/copy_elision)

If a function returns a class type by value, and the return statement's expression is the name of a non-volatile object with automatic storage duration, which isn't the function parameter, or a catch clause parameter, and which has the same type (ignoring top-level cv-qualification) as the return type of the function, then copy/move is omitted. When that local object is constructed, it is constructed directly in the storage where the function's return value would otherwise be moved or copied to. This variant of copy elision is known as NRVO, "named return value optimization".


sample is a class type: check
fun() is specified to return it by value: check
return statement's entire expression is just the name of a local variable: check
the return type and the local variable's types are the same: check

so when fun() executes the line "sample t;", it is calling the default constructor for main()'s local variable s3, and when it executes "t=s;", it is calling operator= on that main's s3

PS: and yes, fix that operator= return type
Last edited on
To: Cubbi

I used gdb to check the address of object 't' inside fun() and object 's3' inside main(). Both are same.

Thanks a lot for the explanation.

Topic archived. No new replies allowed.