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
?
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.
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.
- 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With