【发布时间】:2012-10-01 23:39:36
【问题描述】:
在lecture about universal references 中,Scott Meyers(大约在第 40 分钟)说,作为通用引用的对象在使用之前应该转换为真实类型。换句话说,只要有一个具有通用引用类型的模板函数,就应该在使用运算符和表达式之前使用std::forward,否则可能会复制该对象。
我对此的理解在以下示例中:
#include <iostream>
struct A
{
A() { std::cout<<"constr"<<std::endl; }
A(const A&) { std::cout<<"copy constr"<<std::endl; }
A(A&&) { std::cout<<"move constr"<<std::endl; }
A& operator=(const A&) { std::cout<<"copy assign"<<std::endl; return *this; }
A& operator=(A&&) { std::cout<<"move assign"<<std::endl; return *this; }
~A() { std::cout<<"destr"<<std::endl; }
void bar()
{
std::cout<<"bar"<<std::endl;
}
};
A getA()
{
A a;
return a;
}
template< typename T >
void callBar( T && a )
{
std::forward< T >( a ).bar();
}
int main()
{
{
std::cout<<"\n1"<<std::endl;
A a;
callBar( a );
}
{
std::cout<<"\n2"<<std::endl;
callBar( getA() );
}
}
正如预期的那样,输出是:
1
constr
bar
destr
2
constr
move constr
destr
bar
destr
问题真的是为什么需要这样做?
std::forward< T >( a ).bar();
我尝试不使用 std::forward,它似乎工作正常(输出相同)。
同样,为什么他建议在带有右值的函数内部使用move? (答案与 std::forward 相同)
void callBar( A && a )
{
std::move(a).bar();
}
我知道std::move 和std::forward 都只是转换为适当的类型,但上述示例中真的需要这些转换吗?
奖励:如何修改示例以生成传递给该函数的对象的副本?
【问题讨论】:
-
你没问多少同样的问题就打败了我。我也在寻找这方面的解释。
-
@Vikas 那么,这是否意味着我的理解是正确的?您确实需要使用右值的移动函数吗?
-
我的意思是我看了他的演讲后也有类似的疑惑。我也打算在这里问这个问题:-)。
-
在 callBar 中移动有什么意义,您不会复制?
标签: c++ c++11 move-semantics