是否总是声明特殊的成员函数?

Are the special member functions always declared?

本文关键字:成员 函数 声明 是否      更新时间:2023-10-16

在标准§12中,每个特殊成员函数都有一组使其为implicitly declared as defaulted的规则和另一组使其为a defaulted [special member function to be] defined as deleted的规则。

这使得它似乎(在我看来)有3种潜在的状态,当没有用户声明版本的特殊成员函数存在:声明和定义(defaulted),声明和未定义(deleted),和未声明。这准确吗?如果是这样,有什么理由反对删除"未声明"选项?

* declared as defaulted似乎是一个错误,它不应该被"定义"为默认值吗?

已删除的构造函数与隐式未声明的构造函数的区别在于已删除的构造函数参与重载解析,而不存在的构造函数不参与重载解析。

的例子:

这个类是默认可构造的。编译器不会隐式地为它声明默认构造函数。

struct A
{
    template <class ...T>
    A(T...) {}
};
int main()
{
    A a;  // ok
}

如果编译器为它声明了一个默认构造函数,并且这个默认构造函数被定义为deleted,那么A就不是默认可构造的。可以用以下命令模拟:

struct A
{
    A() = delete;  // pretend the compiler implicitly declared and defined this
    template <class ...T>
    A(T...) {}
};
int main()
{
    A a;
}
error: call to deleted constructor of 'A'
    A a;
      ^

move构造函数也出现了类似的问题。如果编译器决定隐式声明它并将其定义为已删除,则不能从右值构造这样的类,即使它具有可行的复制构造函数:

#include <type_traits>
struct A
{
    A();
    A(const A&);
    A(A&&) = delete;  // pretend compiler declared and defined
};
int main()
{
    A a = std::declval<A>();
}
error: call to deleted constructor of 'A'
    A a = std::declval<A>();
      ^   ~~~~~~~~~~~~~~~~~

但是如果编译器没有隐式声明一个删除的move构造函数,那么事情就正常工作了:

#include <type_traits>
struct A
{
    A();
    A(const A&);
};
int main()
{
    A a = std::declval<A>();  // ok
}
事实上,如果编译器确实为A隐式声明了一个删除的move构造函数,那么在c++ 11中重新编译时,将会有大量坏掉的c++ 98/03代码!: -)

我不太同意你的总结:

基本上有三种状态:User Defined, DeletedCompiler Generated

  • 声明和定义
    • 这意味着用户已经在类中显式地声明了它们并提供了定义。
  • 声明并删除
    • 这意味着用户已明确声明它们已被删除(即它们不可用)。
  • 未申报
    • 用户没有提供声明(因此不能提供定义)。
      在这种情况下,编译器会生成一个版本的方法。