是否始终声明特殊成员函数?

时间:2011-12-25 03:42:56

标签: c++ c++11

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

这似乎(对我而言)当特殊成员函数没有用户声明的版本时,有3种可能的状态:声明和定义(defaulted),声明和未定义(deleted ),并且未宣布。这准确吗?如果是这样,有什么意义,而不是削减'未申报'选项?

* declared as defaulted似乎是一个错误,不应该被“定义”为违约吗?

2 个答案:

答案 0 :(得分:5)

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

示例:

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

struct A
{
    template <class ...T>
    A(T...) {}
};

int main()
{
    A a;  // ok
}

如果编译器确实为它声明了默认构造函数,并且该默认构造函数被定义为已删除,那么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;
      ^

移动构造函数出现类似问题。如果编译器决定隐式声明它并将其定义为已删除,则无法从rvalue构造这样的类,即使它具有可行的复制构造函数:

#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>();
      ^   ~~~~~~~~~~~~~~~~~

但是如果编译器没有隐式声明一个已删除的移动构造函数,那么事情就会起作用:

#include <type_traits>

struct A
{
    A();
    A(const A&);
};

int main()
{
    A a = std::declval<A>();  // ok
}

实际上,如果编译器 隐式声明了A的删除移动构造函数,那么在C ++中重新编译时会出现大量破解的C ++ 98/03代码11! : - )

答案 1 :(得分:0)

我不确定我同意你的摘要:

基本上有三种状态:User DefinedDeletedCompiler Generated

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