默认移动成员定义为已删除,而未定义特殊成员?

Defaulted move members defined as deleted, when no special members defined?

本文关键字:成员 未定义 删除 移动 定义 默认      更新时间:2023-10-16

在Accu 2014的一次演讲中,有一张幻灯片基本上是这样写的:

如果用户声明没有特殊成员函数(构造函数/析构函数/operator=(,则"默认移动成员定义为已删除"。幻灯片 21,此处。

然而,这个简单的程序将打印移动函数被调用:

#include <stdio.h>
#include <utility>
struct Foo {
Foo() { printf("Foo()n"); }
Foo(const Foo &) { printf("Foo(const Foo &)n"); }
Foo(Foo &&) { printf("Foo(Foo &&)n"); }
~Foo() { printf("~Foo()n"); }
Foo &operator=(const Foo &) { printf("Foo::operator=(const Foo &)n"); return *this; }
Foo &operator=(Foo &&) { printf("Foo::operator=(Foo &&)n"); return *this; }
};
struct Baz {
Foo f;
};
int main() {
Baz b;
Baz c(std::move(b));
b = Baz();
}

输出:

Foo()
Foo(Foo &&)
Foo()
Foo::operator=(Foo &&)
~Foo()
~Foo()
~Foo()

在程序中,Baz没有任何特殊功能,但似乎调用了移动函数,这违反了幻灯片中的规则,因为应该删除移动函数。

幻灯片错了吗?我误解了什么吗?关于此的标准是否发生了变化(我尝试使用-std=c++11/14/17编译,相同的结果(?

你误读了幻灯片。我将在此处复制该幻灯片的全文:

  • 如果默认的特殊成员必须执行非法操作,例如调用另一个已删除的函数,则"默认"可能表示"已删除"。
  • 定义为已删除的默认移动成员实际上表现为未声明。
    • 不,我不是在开玩笑!

它的意思是:"如果默认的特殊成员必须做一些非法的事情,它被定义为删除。如果默认移动成员定义为已删除,则它实际上的行为就像根本没有声明一样。

您的解释错过了粗体如果。这并不是说移动默认移动成员将始终被删除。它的意思是,如果删除默认的移动成员,则认为它根本没有声明(C++11(或不参与重载解析(C++14+(,这实际上与不存在相同。换句话说,这样的类在移动时将静默地回退到执行复制。