Std :: forward and copy constructor
I recently started using C ++. And I have a question about std :: forward with lvalue reference and rvalue reference. In my understanding, Func (mc) in the following code is supposed to call Func (T & t) due to the template parameter inference rule. And the copy constructor MyClass must be called inside the function with the message "copy constructor". However, I cannot get it when I run the program. I have verified that std :: forwad with rvalue reference and copy constructor works well on other strings. Please help me understand what is going on in the code. If I make a slight mistake or misunderstanding, I am sorry for taking the time. Thank you very much.
class MyClass {
public:
MyClass() { printf("constructor.\n"); };
MyClass(MyClass&) { printf("copy constructor.\n"); };
MyClass(const MyClass&) { printf("const copy constructor.\n"); };
MyClass(MyClass&&) { printf("move constructor.\n"); };
int val = 3;
};
template <typename T>
void Func(T&& t) {
T new_t_(std::forward<T>(t));
new_t_.val *= 2;
};
main() {
MyClass mc;
Func(mc); // lvalue <- Func(T&)
Func(MyClass()); // rsvalue <- Func(T&&)
printf("mc.val=%d\n", mc.val); // this is for check
MyClass mc2(mc); // this is for check of copy constructor
}
Displayed when the program is started,
constructor.
constructor.
move constructor.
mc.val=6
copy constructor.
I think it should have a "copy constructor" between the first and second "constructor" posts.
Thanks again.
source to share
Func(mc);
This call will output T
as MyClass&
. Pay attention to the link. This is because C ++ introduces perfect forwarding: a forwarding reference such as a function parameter T&&
Func
will be output as an lvalue reference if the corresponding function argument is an lvalue-expression; otherwise (for x and prvalues) it will not be inferred as a reference type.
The type inferred to T
will then be dumped using &&
a function parameter T&& t
to form the final type of the function parameter. In the case Func(mc)
, T == MyClass&
therefore the function parameter becomes MyClass& &&
compressed to MyClass&
.
Since T == MyClass&
, declaring a local variable new_t_
will declare a reference in this case. No new object will be created:
template <>
void Func<MyClass&>(MyClass& t) {
MyClass& new_t_(std::forward<MyClass&>(t));
new_t_.val *= 2;
}
Func(MyClass());
Here, the function argument is a prvalue expression MyClass()
. T
will output to MyClass
(no link). The created instance of the function template looks like this:
template <>
void Func<MyClass>(MyClass&& t) {
MyClass new_t_(std::forward<MyClass>(t));
new_t_.val *= 2;
}
If you want to copy / move a function argument to a local variable, the metafunction std::decay
can be used, or more specifically for the OP's problem, metafile std::remove_reference
. For example.
template <typename T>
void Func(T&& t) {
using DT = typename std::decay<T>::type;
DT new_t_(std::forward<T>(t));
new_t_.val *= 2;
}
source to share