Initialising a class object with the return value of a function

Hello,

I’ve been playing around a bit with functions returning a class object. There’s one situation where I don’t quite follow what’s happening:

I’ve written the function do_something that creates a class object, assigns it some value and then returns that object. Please see code below.

Since I’m returning by value I would have expected the original, local, ‘c’ to be destroyed and a copy of it to be returned. If so, for the code below, I should see something like:

Default constructor called. (for ‘c’ in do_something)
Destructor called. (when the local c in do_something goes out of scope)
Copy constructor called. (when ‘c1’ in main is initialized with the copy of ‘c’)
Length: 4, Width: 3. (for << c1 in main)
I just called do_something. (also in main)
Length: 4, Width: 3. (for c1.print in main)
Destructor called. (when ‘c1’ in main goes out of scope)


Instead I get:

Default constructor called.
Length: 4, Width: 3.
I just called do_something.
Length: 4, Width: 3.
Destructor called.


Can you see where my thinking is going wrong? What happens (in the program/with memory) when do_something returns c?


Code:
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>


class class1{
    private:
        int* length;
        int* width;
        
    public:
        class1(){
            length  = new int(0);
            width   = new int(0);
            std::cout << "Default constructor called." << std::endl;
        }
        
        class1(const class1& c){
            length  = new int(*(c.length));
            width   = new int(*(c.width));
            std::cout << "Copy constructor called." << std::endl;
        }
        
        class1& operator= (const class1& c){
            *length = *(c.length);
            *width  = *(c.width);
            std::cout << "Assignment operator called." << std::endl;
            return *this;
        }
        
        ~class1(){
            delete length;
            delete width;
            std::cout << "Destructor called." << std::endl;
        }
        
        void print() const{
            std::cout << "Length: " << *length << ", Width: " << *width << "." << std::endl;
        }
        
        void set_values(int l, int w){
            *length = l;
            *width  = w;
        }
    
};

std::ostream& operator<<(std::ostream& os, const class1& c){
    c.print();
    return os;
}


class1 do_something(int length, int width){
    class1 c;
    c.set_values(length, width);
    return c;
}

int main()
{
    class1 c1 = do_something(4,3);
    std::cout << c1 << "I just called do_something." << std::endl;
    c1.print();
    
    // calls, as expected, default constructor, copy constructor, destructor, destructor
    /*class1 c1;
    class1 c2 = c1;*/
    
    // calls, as expected, default constructor (2x), assignment operator, destructor (2x)
    /*class1 c1;
    class1 c2;
    c1 = c2;*/
}
Hi Yanson,

thanks for your fast answer, that looks like it's the solution.

Thank you very much!
Last edited on
Topic archived. No new replies allowed.