C++, rvalue references in function parameters

浪子不回头ぞ 提交于 2019-12-04 16:26:59

问题


I'm trying to understand rvalue references. I have seen how they are used in constructors, with things like std::move and std::forward, but I still don't understand why this doesn't work:

void func(string&& str)
{
    cout << str << endl;
}
int main(int argc, char* argv[])
{
    string s("string");
    func(s);
}

And this does:

template<typename T>
void func(T&& str)
{
    cout << str << endl;
}
int main(int argc, char* argv[])
{
    string s("string");
    func(s);
}

Why does it work with the function template version?


回答1:


Like @Peter said, the type of T is deduced as string&, and C++’s reference-collapsing rule says:

T& & ⇒ T& // from C++98
T&& & ⇒ T& // new for C++0x
T& && ⇒ T& // new for C++0x
T&& && ⇒ T&& // new for C++0x

So func’s instantiation is actually:

void func(string& str)

And it works.




回答2:


Some formal explanation in addition to @songyuanyao's answer:

N4296::14.8.2.1 [temp.deduct.call]:

Template argument deduction is done by comparing each function template parameter type (call it P) with the type of the corresponding argument of the call (call it A) as described below.

N4296::14.8.2.1/3 [temp.deduct.call]:

A forwarding reference is an rvalue reference to a cv-unqualified template parameter. If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.

The Standard also provides the following example:

template <class T> int f(T&& heisenreference);
template <class T> int g(const T&&);
int i;
int n1 = f(i); // calls f<int&>(int&)
int n2 = f(0); // calls f<int>(int&&)
int n3 = g(i); // error: would call g<int>(const int&&)

That's exactly your case.




回答3:


Because inside of a template && has a different meaning, it's called universal reference.

a template function with a && parameter (unversal reference) means the parmeter can be used as reference or rvalue-reference.

In your case the template is deduced as string& and that's why it works.

To work with the raw function you have to do this:

void func(string&& str)
{
    cout << str << endl;
}
int main(int argc, char* argv[])
{
    string s("string");
    func(std::move(s)); // move the string
    func(std::string("string")); // this is an rvalue and it is fine
}

A complete explanation about universal references can be found here: https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers



来源:https://stackoverflow.com/questions/30339922/c-rvalue-references-in-function-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!