这似乎是已经提出的最相关的问题。
Whats the difference between std::move and std::forward
但每个答案都不同并且适用并且说的略有不同。所以我很困惑。
我有以下情况。
emplaceBackInternal()
中的T的构造函数(如果我错了,请另外说明。)守则:
template<typename T>
class Container
{
std::size_t length;
T* buffer;
public:
void push_back(T const& value)
{
resizeIfRequired();
pushBackInternal(value);
}
template<typename... Args>
void emplace_back(Args&&... args)
{
resizeIfRequired();
emplaceBackInternal(std::forward<T>(arg)...);
}
void push_back(T&& value)
{
resizeIfRequired();
// Is this forward correct or should it be move
moveBackInternal(std::forward<T>(value));
}
private:
void pushBackInternal(T const& value)
{
// Copy construct object into buffer;
new (buffer + length) T(value);
++length;
}
template<typename... Args)
void emplaceBackInternal(Args&&... args)
{
// Construct object into buffer using arguments;
new (buffer + length) T(std::forward<T>(args)...);
++length;
}
void moveBackInternal(T&& value)
{
// Move construct object into buffer;
// Is this forward correct or should it be move
new (buffer + length) T(std::forward<T>(value));
++length;
}
};
我在这里包括所有三个,将三个函数与前面提到的答案中提供的答案进行比较。主要原因是move
和construct
看起来非常相似,以至于感觉它们应该是相同的。
Answer @Potatoswatter Score 67
std :: forward只有一个用例:施放模板化函数参数
根据这个定义,我应该在std::move
内使用push_back(T&& value)
moveBackInternal(T&& value)
因为该值不是函数的模板参数。
Answer @Howard Hinnant Score 38
如果Y是左值引用,则结果将是左值表达式。 如果Y不是左值参考,则结果将是右值(准确地说是xvalue)表达式。
根据此定义,我可以使用std::move
或std::forward
。
std :: forward用于完全按照传递给函数的方式转发参数。
似乎可以说std::forward
是可以接受的(尽管如果我按照答案中的链接,所有示例都使用模板化函数)。
答案 0 :(得分:5)
在这种情况下:
void push_back(T&& value)
{
resizeIfRequired();
moveBackInternal(std::forward<T>(value)); // (1)
moveBackInternal(std::move(value)); // (2)
}
在此方案中, std::forward<T>(value)
和std::move(value)
相同(在(1)
和(2)
之间无关紧要......所以使用(2)
)。
move
是对xvalue的无条件转换。该行为您提供了T&&
类型的表达式,它始终是一个rvalue。
forward
是一个条件演员。如果T
是左值引用类型,则会产生左值。否则(如果它不是引用类型或右值引用类型),它会产生一个rvalue。在我们的例子中,T
不是引用类型 - 所以我们得到一个右值。
无论哪种方式,我们都会在同一点上结束 - 我们将moveBackInternal
称为value
施放为左值。只是move()
是一种更简单的方法。 forward<T>
有效,但这是不必要的。