是否总是声明特殊的成员函数?
Are the special member functions always declared?
在标准§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
, Deleted
或Compiler Generated
- 声明和定义
- 这意味着用户已经在类中显式地声明了它们并提供了定义。
- 声明并删除
- 这意味着用户已明确声明它们已被删除(即它们不可用)。
- 未申报
- 用户没有提供声明(因此不能提供定义)。
在这种情况下,编译器会生成一个版本的方法。
- 用户没有提供声明(因此不能提供定义)。
相关文章:
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 将公共但非静态的成员函数与ALGLIB集成
- 使用指向成员的指针将成员函数作为参数传递
- 将重载的成员函数传递给函数模板
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 如何在C++中使用非静态成员函数作为回调函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 关联容器的下界复杂性:成员函数与非成员函数
- 在 C++ 中用派生类型重写成员函数
- 链表的泛型函数remove()与成员函数remove)
- 如何将lambda作为模板类的成员函数参数
- constexpr构造函数需要常量成员函数时出现问题
- 将自由函数绑定为类成员函数
- 区分非成员函数和头文件中的成员函数
- 如何从子成员函数修改父公共成员变量
- 保留对其他类的成员函数的引用
- 在运算符重载定义中使用成员函数(const错误)
- 内联如何影响模块接口中的成员函数
- 将成员函数指针作为参数传递给模板方法