jeudi 17 décembre 2020

Copy constructor not getting called at function return

Sorry for the long description, but I'm not sure how can I explain this problem I am facing in short.

I'm having following class from the book C++ Primer Lippman et. at.

// Sales_data.h

class Sales_data {
    friend Sales_data add(const Sales_data&, const Sales_data&);
    friend std::ostream &print(std::ostream&, const Sales_data&);
    friend std::istream &read(std::istream&, Sales_data&);
    friend std::ostream &operator<<(std::ostream&, const Sales_data&);
    friend std::istream &operator>>(std::istream&, Sales_data&);
public:
    // constructors
    Sales_data(); //  = default;
    Sales_data(const std::string &);
    Sales_data(const Sales_data &);
    Sales_data(const std::string &, unsigned, double);
    Sales_data(std::istream &);

    // destructor
    ~Sales_data();

    // operations on Sales_data objects
    std::string isbn() const { return bookNo; }
    Sales_data& combine(const Sales_data&);
    double avg_price() const;
private:
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

And following are the implementation of default constructor, Copy constructor and destructor with logging to enable debugging.


// Sales_data.cpp

Sales_data::Sales_data() {
    std::cout << "<" << __PRETTY_FUNCTION__ << ">:" << this << std::endl;
}

Sales_data::Sales_data(const Sales_data &rhs) {
    std::cout << "<Copy Constructor:" << __PRETTY_FUNCTION__
        << ">:From:" << &rhs << ",To:" << this << std::endl;
    bookNo = rhs.bookNo;
    units_sold = rhs.units_sold;
    revenue = rhs.revenue;
}

Sales_data::~Sales_data() {
    std::cout << "<" << __PRETTY_FUNCTION__ << ">:" << this << std::endl;
}

Driver program for this is :

/// test.cpp
#include <iostream>
#include <fstream>

#include "Sales_data.h"

using namespace std;


Sales_data global;

Sales_data foo_bar(Sales_data arg) {
    Sales_data local = arg, *heap = new Sales_data(global);
    cout << "Before *heap = local; ..." << endl;
    *heap = local;
    cout << "Initializing array pa[4] ..." << endl;
    Sales_data pa[4] = {local, *heap};
    cout << "Done initializing array pa[4] ..." << endl;
    return *heap;

}


int main(int argc, char *argv[]) {
    //v.emplace_back("978-0590353403", 25, 15.99);
    //v.emplace_back("978-0590353404", 25, 15.99);

    Sales_data sd, ret;

    cout << "Now calling foo_bar() ..." << endl;
    ret = foo_bar(sd);
    cout << "Addr =" << &ret << endl;
    cout << "Returned from foo_bar() ..." << endl;

    return 0;
}

Below is the output.

onkar@titan:~/cpp$ ./test
<Sales_data::Sales_data()>:0x55e200b2a160
<Sales_data::Sales_data()>:0x7ffc4f355840
<Sales_data::Sales_data()>:0x7ffc4f355870
Now calling foo_bar() ...
<Copy Constructor:Sales_data::Sales_data(const Sales_data&)>:From:0x7ffc4f355840,To:0x7ffc4f3558a0
<Copy Constructor:Sales_data::Sales_data(const Sales_data&)>:From:0x7ffc4f3558a0,To:0x7ffc4f355700
<Copy Constructor:Sales_data::Sales_data(const Sales_data&)>:From:0x55e200b2a160,To:0x55e20180e2c0  << *heap = new Sales_data(global);
Before *heap = local; ...
Initializing array pa[4] ...
<Copy Constructor:Sales_data::Sales_data(const Sales_data&)>:From:0x7ffc4f355700,To:0x7ffc4f355730  << pa[0] = local
<Copy Constructor:Sales_data::Sales_data(const Sales_data&)>:From:0x55e20180e2c0,To:0x7ffc4f355760  << pa[1] = *heap
<Sales_data::Sales_data()>:0x7ffc4f355790
<Sales_data::Sales_data()>:0x7ffc4f3557c0
Done initializing array pa[4] ...
<Copy Constructor:Sales_data::Sales_data(const Sales_data&)>:From:0x55e20180e2c0,To:0x7ffc4f3558d0 << This point ****
<Sales_data::~Sales_data()>:0x7ffc4f3557c0
<Sales_data::~Sales_data()>:0x7ffc4f355790
<Sales_data::~Sales_data()>:0x7ffc4f355760
<Sales_data::~Sales_data()>:0x7ffc4f355730
<Sales_data::~Sales_data()>:0x7ffc4f355700
<Sales_data::~Sales_data()>:0x7ffc4f3558d0
<Sales_data::~Sales_data()>:0x7ffc4f3558a0
Addr =0x7ffc4f355870
Returned from foo_bar() ...
<Sales_data::~Sales_data()>:0x7ffc4f355870
<Sales_data::~Sales_data()>:0x7ffc4f355840
<Sales_data::~Sales_data()>:0x55e200b2a160
onkar@titan:~/cpp$

In this output, I was expecting copy constructor being called (to copy *heap to ret) when the function foo_bar returns, but this is not happening.

Please help me understand why copy constructor is not getting called.

Aucun commentaire:

Enregistrer un commentaire