假设我有一个只能移动的类型。我们停止现有的默认提供的构造函数,但是右值引用引入了一种新的“风格”,我们可以将其用于签名的移动版本:
class CantCopyMe
{
private:
CantCopyMe (CantCopyMe const & other) = delete;
CantCopyMe & operator= (CantCopyMe const & other) = delete;
public:
CantCopyMe (CantCopyMe && other) {
/* ... */
}
CantCopyMe & operator= (CantCopyMe && other) {
/* ... */
}
};
我最近认为您总是应该通过右值引用传递可移动类型。现在看起来只有非常特殊的情况需要这样做......就像这两个一样。如果你把它们放在任何地方,事情似乎大部分时间都可以工作,但我只是发现编译器没有运行部分代码转移所有权的情况。
(这种情况就像将变量中保存的唯一指针传递给带有参数std::move
的东西unique_ptr<foo> &&
......但注意到调用站点的变量没有被清空。更改参数以unique_ptr<foo>
修复它并且它被正确地清空,从而防止双重删除。:-/我没有孤立为什么这个似乎在其他地方工作时不好,但确凿证据是它第一次工作但不是随后的电话。)
我相信这是有充分理由的,你们中的许多人都可以明确地总结出来。与此同时,我开始像一个优秀的货物狂热程序员一样四处走动,去掉 &&s。
但是如果你正在编写一个模板类,它看起来像这样呢?
template <class FooType>
class CantCopyMe
{
private:
CantCopyMe (CantCopyMe const & other) = delete;
CantCopyMe & operator= (CantCopyMe const & other) = delete;
public:
template<class OtherFooType>
CantCopyMe (CantCopyMe<OtherFooType> && other) {
/* ... */
}
template<class OtherFooType>
CantCopyMe & operator= (CantCopyMe<OtherFooType> && other) {
/* ... */
}
};
出于某种原因,这是一种不好的做法,当 OtherFooType 和 FooType 不相同时,您应该单独突破……然后它只是按值传递?
template <class FooType>
class CantCopyMe
{
private:
CantCopyMe (CantCopyMe const & other) = delete;
CantCopyMe & operator= (CantCopyMe const & other) = delete;
public:
CantCopyMe (CantCopyMe && other) {
/* ... */
}
CantCopyMe & operator= (CantCopyMe && other) {
/* ... */
}
template<class OtherFooType>
CantCopyMe (CantCopyMe<OtherFooType> other) {
/* ... */
}
template<class OtherFooType>
CantCopyMe & operator= (CantCopyMe<OtherFooType> other) {
/* ... */
}
};