自动生成的移动构造函数,成员不可移动
Automatically generated move constructor with not movable members
我遇到了一个非常有趣的情况,因为我正在编写的代码可以编译,尽管我很惊讶它确实如此,所以我想请你接受。
情况是这样的。我有一个 class 删除了移动和复制构造函数,它有用户定义的赋值运算符:
struct A {
A() { }
A(const A&) = delete;
A(A&& ) = delete;
A& operator=(const A& ) { return *this; }
A& operator=(A&& ) { return *this; }
};
我还有一个 class,A
是唯一的成员。在此 class 中,我定义了复制构造函数,但我将移动构造函数保留为默认值,并通过调用交换函数定义了赋值运算符:
class B{
public:
A a;
B()
: a{}
{ }
B(const B&)
: a{}
{ }
B(B&& other) = default;
};
int main() {
B b1;
B b2(std::move(b1)); // compiles??
}
考虑到它不能简单地调用移动或复制构造函数 A,为什么默认移动构造函数可以工作?我正在使用 gcc 4.8.4.
我原来的回答是错误的,所以我重新开始。
在 [class.copy] 中,我们有:
A defaulted copy/
move constructor for a class X is defined as deleted (8.4.3) if X has:
— [...]
— a potentially constructed subobject type M (or array thereof) that cannot be copied/moved because
overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a
function that is deleted or inaccessible from the defaulted constructor,
— [...]
该要点适用于 B(B&& other) = default;
,因此移动构造函数被定义为已删除。这似乎会破坏 std::move()
的编译,但我们也有(通过 defect 1402 的解析):
A defaulted move constructor that is defined as deleted is ignored by overload resolution (13.3, 13.4). [ Note:
A deleted move constructor would otherwise interfere with initialization from an rvalue which can use the
copy constructor instead. —end note ]
无视是关键。因此,当我们这样做时:
B b1;
B b2(std::move(b1));
尽管删除了 B
的移动构造函数,但这段代码的格式是正确的,因为移动构造函数根本不参与重载决策,而是调用了复制构造函数。因此,B
是 MoveConstructible - 即使您不能通过其移动构造函数构造它。
我遇到了一个非常有趣的情况,因为我正在编写的代码可以编译,尽管我很惊讶它确实如此,所以我想请你接受。
情况是这样的。我有一个 class 删除了移动和复制构造函数,它有用户定义的赋值运算符:
struct A {
A() { }
A(const A&) = delete;
A(A&& ) = delete;
A& operator=(const A& ) { return *this; }
A& operator=(A&& ) { return *this; }
};
我还有一个 class,A
是唯一的成员。在此 class 中,我定义了复制构造函数,但我将移动构造函数保留为默认值,并通过调用交换函数定义了赋值运算符:
class B{
public:
A a;
B()
: a{}
{ }
B(const B&)
: a{}
{ }
B(B&& other) = default;
};
int main() {
B b1;
B b2(std::move(b1)); // compiles??
}
考虑到它不能简单地调用移动或复制构造函数 A,为什么默认移动构造函数可以工作?我正在使用 gcc 4.8.4.
我原来的回答是错误的,所以我重新开始。
在 [class.copy] 中,我们有:
A defaulted copy/ move constructor for a class X is defined as deleted (8.4.3) if X has:
— [...]
— a potentially constructed subobject type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
— [...]
该要点适用于 B(B&& other) = default;
,因此移动构造函数被定义为已删除。这似乎会破坏 std::move()
的编译,但我们也有(通过 defect 1402 的解析):
A defaulted move constructor that is defined as deleted is ignored by overload resolution (13.3, 13.4). [ Note: A deleted move constructor would otherwise interfere with initialization from an rvalue which can use the copy constructor instead. —end note ]
无视是关键。因此,当我们这样做时:
B b1;
B b2(std::move(b1));
尽管删除了 B
的移动构造函数,但这段代码的格式是正确的,因为移动构造函数根本不参与重载决策,而是调用了复制构造函数。因此,B
是 MoveConstructible - 即使您不能通过其移动构造函数构造它。