有些代码无法编译,因为push_back试图调用MoveOnlyClass中的副本构造函数,该副本构造函数已删除:
function fetchData(params: IProps<true>): Promise<IFoo[]>;
function fetchData(params: IProps<false>): Promise<IBar[]>;
function fetchData<T extends boolean>(params: IProps<T>) {
return apiService('/user/data', params)
.then(
(data: IExternalFoo[] | IExternalBar[]) =>
params.isExtended
? (data as IExternalFoo[]).map(mapExternalFoo)
: (data as IExternalBar[]).map(mapExternalBar)
);
}
为什么会这样?向量唯一要调用的当然是move构造函数。将对象移到矢量中的正确方法是什么?
答案 0 :(得分:5)
删除复制构造函数/副本分配函数也将隐式删除移动构造函数/移动分配函数。如果要使对象可移动但不可复制,则还需要default
移动构造函数。
class MoveOnlyClass
{
public:
MoveOnlyClass() {};
MoveOnlyClass& operator=(const MoveOnlyClass& other) = delete;
MoveOnlyClass(const MoveOnlyClass& other) = delete;
MoveOnlyClass& operator=(MoveOnlyClass&& other) = default;
MoveOnlyClass(MoveOnlyClass&& other) = default;
};
//Will now compile as you expect
int main()
{
std::vector<MoveOnlyClass> vec;
vec.push_back(std::move(MoveOnlyClass()));
}
此外,std::move(T())
是多余的;像这样就地构造一个对象将已经使其成为R值,并在不需要时使用std::move
可能会阻止某些编译器优化(例如,Copy Ellision)。
答案 1 :(得分:2)
@Xirema的回答密封了代码中有关该问题的内容,并解释了为什么是这种情况。
我只想备份语言规范中的适当摘录,以使事情变得正式。因此,来自[class.copy.ctor¶8]:
(8)如果类X的定义未明确声明move构造函数,则非显式类将隐式声明为默认当且仅当
- (8.1) X没有用户声明的副本构造器,
为此,我们应该添加声明为delete仍在声明。因此,根据此,在您的情况下,我们不会得到隐式声明的move构造器,因为我们已经有一个用户声明的副本构造器。
进一步,在[dcl.fct.def.delete¶3]下:
一个人可以将某个班级设为不可复制, 复制构造函数和复制赋值运算符和 然后提供move构造函数和move的默认定义 赋值运算符。