面试题:C++ 中类定义中 delete 关键字和 default 关键字的作用?

在 C++ 中,deletedefault 是两个用于控制类成员函数行为的关键字。它们通常用于显式地管理类的特殊成员函数(如构造函数、析构函数、拷贝构造函数、赋值运算符等)的生成和使用。


1. delete 关键字的作用

delete 用于显式地禁用类的某些成员函数或转换函数,使其不能被调用或使用。

(1)禁用特殊成员函数

  • 通过将特殊成员函数标记为 delete,可以阻止编译器自动生成该函数。
  • 常见的用途包括禁用拷贝构造函数、赋值运算符等。

示例:禁用拷贝构造函数和赋值运算符

class NonCopyable {
public:
    NonCopyable() = default;

    // 禁用拷贝构造函数
    NonCopyable(const NonCopyable&) = delete;

    // 禁用赋值运算符
    NonCopyable& operator=(const NonCopyable&) = delete;
};

int main() {
    NonCopyable obj1;
    // NonCopyable obj2 = obj1; // 错误:拷贝构造函数被禁用
    // obj2 = obj1; // 错误:赋值运算符被禁用
    return 0;
}

(2)禁用转换函数

  • 通过将转换函数标记为 delete,可以阻止某些隐式类型转换。

示例:禁用从 intMyClass 的隐式转换

class MyClass {
public:
    MyClass(int value) {}

    // 禁用从 double 到 MyClass 的隐式转换
    MyClass(double) = delete;
};

int main() {
    MyClass obj1(10); // 合法
    // MyClass obj2(10.5); // 错误:从 double 到 MyClass 的转换被禁用
    return 0;
}

(3)禁用某些函数重载

  • 通过将某些函数重载标记为 delete,可以阻止调用特定的函数版本。

示例:禁用特定参数类型的函数重载

void func(int value) {}
void func(double) = delete; // 禁用 double 版本的 func

int main() {
    func(10); // 合法
    // func(10.5); // 错误:double 版本的 func 被禁用
    return 0;
}

2. default 关键字的作用

default 用于显式地要求编译器生成默认的特殊成员函数。

(1)生成默认的特殊成员函数

  • 通过将特殊成员函数标记为 default,可以显式地要求编译器生成默认实现。
  • 常见的用途包括生成默认构造函数、析构函数、拷贝构造函数、赋值运算符等。

示例:显式生成默认构造函数和析构函数

class MyClass {
public:
    MyClass() = default; // 显式生成默认构造函数
    ~MyClass() = default; // 显式生成默认析构函数
};

(2)恢复被抑制的默认函数

  • 如果类的某些行为(如定义了移动构造函数)导致编译器不再自动生成默认的特殊成员函数,可以使用 default 恢复默认行为。

示例:恢复默认的拷贝构造函数

class MyClass {
public:
    MyClass() = default;

    // 定义移动构造函数
    MyClass(MyClass&&) {}

    // 恢复默认的拷贝构造函数
    MyClass(const MyClass&) = default;
};

3. deletedefault 的对比

特性deletedefault
作用禁用某些成员函数或转换函数显式生成默认的特殊成员函数
适用场景禁用拷贝、赋值、转换等恢复或显式生成默认函数
常见用途禁用拷贝构造函数、赋值运算符等生成默认构造函数、析构函数等

4. 使用场景总结

(1)delete 的使用场景

  • 禁用拷贝构造函数和赋值运算符,实现不可拷贝的类。
  • 禁用某些隐式类型转换。
  • 禁用特定的函数重载。

(2)default 的使用场景

  • 显式生成默认构造函数、析构函数等。
  • 恢复被抑制的默认特殊成员函数。

5. 示例代码

class MyClass {
public:
    MyClass() = default; // 显式生成默认构造函数
    MyClass(const MyClass&) = delete; // 禁用拷贝构造函数
    MyClass& operator=(const MyClass&) = delete; // 禁用赋值运算符

    // 显式生成默认析构函数
    ~MyClass() = default;
};

int main() {
    MyClass obj1;
    // MyClass obj2 = obj1; // 错误:拷贝构造函数被禁用
    // obj2 = obj1; // 错误:赋值运算符被禁用
    return 0;
}

6. 总结

  • delete:用于禁用某些成员函数或转换函数,防止不期望的行为。
  • default:用于显式生成默认的特殊成员函数,确保类的行为符合预期。

在面试中,理解 deletedefault 的作用并能够举例说明其使用场景是非常重要的。

THE END
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容