Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why my object still gets copied when I tried to return a reference

class Obj {
public:
    Obj(int aa, int bb): a(aa), b(bb) {}
    Obj(const Obj& o) {a = o.a; b = o.b;std::cout << "copying" << std::endl;}
    Obj(Obj&& o) {a = o.a; b = o.b;std::cout << "moving" << std::endl;}
    int a;
    int b;
};
const Obj& Min(const Obj &o1, const Obj &o2) {
    if (o1.a > o2.a) {
        return o1;
    } else {
        return o2;
    }
}
int main() {
    using namespace std;

    auto o1 = Obj(1,1);
    auto o2 = Obj(2,2);
    auto res = Min(o1, o2);

    cout << res.a << endl;
    res.a = 100;
    cout << o1.a << endl;
    cout << o2.a << endl;

    return 0;
}

The program still prints a word copying which indicates that the copy constructor is activated. Where is the constructor called then ? Why the function does not return a reference of o1 so that modifying the value of res will also changing the value of o1 ?

like image 567
coin cheung Avatar asked Dec 11 '22 04:12

coin cheung


2 Answers

The copy is done in the statement:

auto res = Min(o1, o2);

Min() return type is const Obj&. The auto above will be deduced to Obj, not const Obj& (i.e., res type will be Obj). res, which is an object, is initialized by means of the copy constructor (i.e., Obj::Obj(const Obj&)), therefore a copy construction takes place.

If you write instead:

auto& res = Min(o1, o2)

res will be of type const Obj& and no copy construction takes place there, since res will be a reference, not an object.

like image 144
ネロク・ゴ Avatar answered May 16 '23 10:05

ネロク・ゴ


This has to do with how auto deduces the type:

From the CPP working draft (N4713):

10.1.7.4.1 Placeholder type deduction [dcl.type.auto.deduct]
...
4. If the placeholder is the auto type-specifier, the deduced type T' replacing T is determined using the rules for template argument deduction.

And:

17.9.2.1 Deducing template arguments from a function call [temp.deduct.call]
...
2. If P is not a reference type:
...
(2.3) — If A is a cv-qualified type, the top-level cv-qualifiers of A’s type are ignored for type deduction.

  1. If P is a reference type, the type referred to by P is used for type deduction.

So the auto in the below statement

auto res = Min(o1, o2);

deduces res as Obj thus invoking the copy-constructor at the assignment.

So modifying the above to this:

auto& res = Min(o1, o2);

will enable auto to deduce res as const Obj&.

But if you do this, res cannot be modified in main as it is a const reference

like image 30
P.W Avatar answered May 16 '23 08:05

P.W