参考以下代码,我不明白为什么使用move constructor
和lvalue
同时调用rvalue
。当我将copy ctor
传递给lvalue
方法时,我希望打印push
。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class my_obj
{
public:
my_obj()
{
cout << "default ctor\n";
}
my_obj(const my_obj& other)
{
cout << "copy ctor\n";
}
my_obj(my_obj&& other)
{
cout << "move ctor\n";
}
};
class test
{
public:
template<typename T>
void push(T&& object)
{
print(forward<T>(object));
}
template<typename T>
void print(T&& a)
{
cout << "move\n";
my_obj temp = forward<T>(a);
}
template<typename T>
void print(T& a)
{
cout << "val\n";
my_obj temp = forward<T>(a);
}
};
int main()
{
my_obj obj;
test f;
f.push(obj); // why is move ctor called here? shouldnt it be copy ctor since not rvalue
cout << "\nPUSHING TEMP\n\n";
f.push(my_obj {});
}
输出:
default ctor
val
move ctor
PUSHING TEMP
default ctor
move
move ctor
答案 0 :(得分:4)
在这里:
template<typename T>
void print(T& a)
{
cout << "val\n";
my_obj temp = forward<T>(a);
}
a
不是转发引用,它是左值引用。类型T
不是引用类型。因此forward<T>(a)
与move(a)
的行为相同。转发引用的特殊情况是模板参数推导为引用类型,使用引用类型转发会产生左值。
您只想要my_obj temp = a;
答案 1 :(得分:2)
调用移动构造函数是因为您使用std::forward
而没有转发引用(请不要这样做)。基本上,这条线是罪魁祸首:
my_obj temp = forward<T>(a);
此处T
是my_obj
。请记住,std::forward
只是一个荣耀的演员。在您的情况下,它相当于:
my_obj temp = static_cast<my_obj&&>(a);
因此,您将a
转换为右值引用,并且rvalue具有移动语义,因此您可以看到正在调用的移动构造函数。你基本上得到了std::move
的行为。