C++自动生成带有用户声明析构函数的移动构造函数

C++ Auto Generates Move Constructor With User Declared Destructor?

本文关键字:析构函数 移动 构造函数 声明 用户 自动生成 C++      更新时间:2023-10-16

根据cpp首选项和这个答案,如果有用户声明的析构函数,C++不应该自动生成移动构造函数。但是,使用 Clang 在实践中检查这一点,我看到了一个自动生成的移动构造函数。以下代码打印"is_move_constructible:1":

#include <iostream>
#include <type_traits>
struct TestClass
{
  ~TestClass()
  {}
};
int main( int argc, char** argv )
{
  std::cout << "is_move_constructible: " << std::is_move_constructible<TestClass>::value << std::endl;
}

我是否误解了"没有用户声明的析构函数"或 std::is_move_constructible?我正在使用"-std=c++14"和Apple LLVM版本7.0.2(clang-700.1.81(进行编译。

没有移动构造函数的类型,但具有接受const T&参数的复制构造函数,满足std::is_move_constructible和隐式声明的复制构造函数具有T::T(const T&)形式

如果删除隐式声明的复制构造函数,则不满足std::is_move_constructible,如下所示。

#include <iostream>
#include <type_traits>
struct TestClass
{
  ~TestClass() {}
  TestClass(const TestClass&) = delete;
};
int main( int argc, char** argv )
{
  std::cout << "is_move_constructible: " << std::is_move_constructible<TestClass>::value << std::endl;
}

对于 C++11 代码,@Alper接受的答案很好。但是为了使您的代码面向未来,请注意,从 Clang 3.7 开始(不知道对应于哪个 Apple 版本,当然你可以找到(,使用 -std=c++1z -Wdeprecated 将生成以下内容

warning: definition of implicit copy constructor for 'TestClass' is deprecated because it has a user-declared destructor [-Wdeprecated]
  ~TestClass()
  ^

现场示例

草案 C++1z 标准 N4567 的相关部分是

12.8 复制和移动类对象 [class.copy]

7 如果类定义未显式声明复制构造函数,则 非显式的 1 是隐式声明的。如果类定义 声明移动构造函数或移动赋值运算符, 隐式声明的复制构造函数定义为已删除;否则 它被定义为默认值 (8.4(。如果 类具有用户声明的复制赋值运算符或用户声明的 析构函数

已弃用意味着在用户声明析构函数的情况下,将来的标准可能会停止生成隐式复制构造函数。最佳做法是立即更改代码,使其不依赖于已弃用的行为(即在这种情况下,使类的复制行为显式化(。