C++ 转发引用和右值引用
C++ forwarding reference and r-value reference
我了解转发引用是 "an rvalue reference to a cv-unqualified template parameter",例如
template <class T> void foo(T&& );
这意味着上面的函数可以同时使用左值和右值引用。
有些地方我不明白,例如
template <class T>
class A
{
template <class U>
void foo(T&& t, U&& u)
{
T t2( std::forward(t) ); // or should it be std::move(t)? is T&& forwarding or r-value reference
U u2( std::forward(u) ); // or should it be std::move(u)? I believe U&& is forwarding reference
}
};
上面代码中T&&和U&&都是转发引用吗?
我写了一些代码来测试(VS2015编译器):
class A
{
public:
A(){};
A(const A& rhs)
{
std::cout << "calling 'const A&' l-value" << std::endl;
}
A(A&& rhs)
{
std::cout << "calling ' A&&' r-value" << std::endl;
}
};
template <class T>
class Test
{
public:
void test1(T&& t)
{
T t2(std::forward<T>(t));
}
template <typename X>
void test2(X&& x)
{
T t2( std::forward<T>( x ) );
}
};
void main()
{
A a;
Test<A> test;
test.test1(A());
test.test1(std::move(a));
//test.test1(a); // this doesn't compile. error: cannot convert argument 1 from 'A' to 'A &&', You cannot bind an lvalue to an rvalue reference
test.test2<A>(A());
test.test2<A>( std::move( a ) );
//test.test2<A>( a ); // this doesn't compile. error: cannot convert argument 1 from 'A' to 'A &&', You cannot bind an lvalue to an rvalue reference
}
我期待 test.test1(a);如果 test.test2(a) 转发引用,它们都应该编译,但两者都不编译。
有人可以给我解释一下吗?谢谢!
编辑
- - - - - - - 谢谢你们 - - - - - -
Richard 和 Artemy 是正确的。
这是一个很好的问题,一开始几乎每个人都感到困惑。
template <class T>
class A
{
template <class U>
void foo(T&& t, U&& u);
};
在这个例子中,T
没有推导(你在实例化模板时明确定义它)。
U
是从参数u
.
推导出来的
因此,几乎在所有情况下都是:
std::move(t);
std::forward<U>(u);
are both T&& and U&& forwarding references?
不,只有 U&&
是 转发引用 ,因为 U
是唯一被推导的模板参数。 T
在实例化 A
时已经 "chosen"。
除了 Richard 和 Artemy 指出的之外,当您指定 test.test2<A>( a )
时,类型 X 已经明确定义为 A。
当您将其更改为 test.test2( a )
时,应推导类型 X 并进行编译。
我了解转发引用是 "an rvalue reference to a cv-unqualified template parameter",例如
template <class T> void foo(T&& );
这意味着上面的函数可以同时使用左值和右值引用。
有些地方我不明白,例如
template <class T>
class A
{
template <class U>
void foo(T&& t, U&& u)
{
T t2( std::forward(t) ); // or should it be std::move(t)? is T&& forwarding or r-value reference
U u2( std::forward(u) ); // or should it be std::move(u)? I believe U&& is forwarding reference
}
};
上面代码中T&&和U&&都是转发引用吗?
我写了一些代码来测试(VS2015编译器):
class A
{
public:
A(){};
A(const A& rhs)
{
std::cout << "calling 'const A&' l-value" << std::endl;
}
A(A&& rhs)
{
std::cout << "calling ' A&&' r-value" << std::endl;
}
};
template <class T>
class Test
{
public:
void test1(T&& t)
{
T t2(std::forward<T>(t));
}
template <typename X>
void test2(X&& x)
{
T t2( std::forward<T>( x ) );
}
};
void main()
{
A a;
Test<A> test;
test.test1(A());
test.test1(std::move(a));
//test.test1(a); // this doesn't compile. error: cannot convert argument 1 from 'A' to 'A &&', You cannot bind an lvalue to an rvalue reference
test.test2<A>(A());
test.test2<A>( std::move( a ) );
//test.test2<A>( a ); // this doesn't compile. error: cannot convert argument 1 from 'A' to 'A &&', You cannot bind an lvalue to an rvalue reference
}
我期待 test.test1(a);如果 test.test2(a) 转发引用,它们都应该编译,但两者都不编译。
有人可以给我解释一下吗?谢谢!
编辑 - - - - - - - 谢谢你们 - - - - - - Richard 和 Artemy 是正确的。
这是一个很好的问题,一开始几乎每个人都感到困惑。
template <class T>
class A
{
template <class U>
void foo(T&& t, U&& u);
};
在这个例子中,T
没有推导(你在实例化模板时明确定义它)。
U
是从参数u
.
因此,几乎在所有情况下都是:
std::move(t);
std::forward<U>(u);
are both T&& and U&& forwarding references?
不,只有 U&&
是 转发引用 ,因为 U
是唯一被推导的模板参数。 T
在实例化 A
时已经 "chosen"。
除了 Richard 和 Artemy 指出的之外,当您指定 test.test2<A>( a )
时,类型 X 已经明确定义为 A。
当您将其更改为 test.test2( a )
时,应推导类型 X 并进行编译。