我通过以下代码传递:
void enqueue(T&& value)
{
move_value_somewhere( T(std::move(value)));
}
void enqueue(const T& value)
{
enqueue(T(value));
}
复制输入参数的第二个函数调用移动输入参数的第一个函数。假设代码是正确的,如果从第二个函数调用值,T(std::move(value))
怎么会不移动值而不是复制它,它可能来自T()
但我不知道为什么。
enqueue(T(value));
首先创建传递值 (T(value)
) 的临时副本。然后,您的移动构造函数enqeue
移动该临时副本。因此,该代码类似于
T copy(value);
enqueue(std::move(copy));
在void enqueue(const T& value)
中,一个临时T
是从value
复制构造的。 然后将该临时传递给void enqueue(T&& value)
。
在void enqueue(T&& value)
中,另一个临时T
是从value
作为输入进行移动构造的(假设T
有一个移动构造函数,否则它将被复制构造)。 然后将该临时传递给move_value_somewhere()
。 该临时T
实际上是不必要的,因为value
已经是右值引用,因此可以直接将其移动到move_value_somewhere()
,例如:
void enqueue(T&& value)
{
move_value_somewhere(std::move(value));
}
在复制构造函数中调用移动构造函数
实际上,事实并非如此,因为显示的代码根本不适用于构造函数,而仅适用于普通的非静态类方法。 那里有很大的不同。构造函数没有返回值,并且不能像此代码那样相互调用。 但它们可以相互委托,但只能从成员初始化列表中委派。 请参阅构造函数和成员初始值设定项列表。
enqueue()
采用T&&
,这仅将其限制为该类型,由于传递参数不会发生构造函数调用,因为它不是值类型。
但是,当您调用enqueue()
时,您将创建一个临时T
该将从您传入const T& value
调用其复制构造函数。
随后,临时成为enqueue()
的参数,进而创建另一个 prvalueT
,这次使用您的(现在)lvalue 参数转换为T&&
初始化,如果T
确实有一个移动构造函数,它将调用它。
否则,如果T
没有移动构造函数(也没有显式删除的构造函数),它将"回退"到调用复制构造函数(如果存在)。
由于您正在传递临时move_value_somewhere()
因此它需要接受T&&
、const T&
或T
- 根据规定类型T
具有可行的构造函数来实现这一切。