=default, =delete

C++构造与拷贝管理
本文探讨了C++中构造函数、拷贝构造、拷贝赋值及析构函数的管理方式。深入分析了=default与=delete的作用,并介绍了如何通过这些特性实现不可拷贝的类。

=default, =delete

=default

如果自己定义了一个ctor,那么编译器就不会再合成一个default ctor
如果强制加上=default, 编译器就会合成一个default ctor

=delete

禁止编译器合成

当被需要时c++编译器能合成的四类函数

构造,拷贝构造,拷贝赋值,析构函数

class Test {
public:
    Test(int i, int j):d1(i), d2(j) {}          //默认构造函数
    Test(const Test& t) = delete;               //拷贝构造
    Test(Test&&) = default;                     
    Test& operator=(const Test&) = default;     //拷贝赋值
    Test& operator=(const Test&&) = delete;
    virtual ~Test() {}                         //析构
private:
    int d1, d2;
}

构造函数可以有多个版本,拷贝构造,拷贝赋值,析构只能有一个版本
下述打//的会编译出错

class Foo {
public:
    Foo(int i): num(i){}
    Foo() = default;

    Foo(const Foo& x):num(x.num) {}
    //Foo(const Foo&) =default;         //不能重载
    //Foo(const Foo&) =delete;          //已经写了,不能delete

    Foo& operator=(const Foo& x) {
        num = x.num;
        return *this;
    }
    //Foo& operator=(const Foo& x) =default;   //不能重载
    //Foo& operator=(const Foo& x) =delete;    //已经写了,不能delete

    //void func1() = default;   //普通函数不能default,可以delete(没意义)
    void fun2() = delete;

    //~Foo() = delete;
    ~Foo() =default;

private:
    int num;
}

实现不可拷贝的类

只要与拷贝有关的构造函数不存在即可

class Nocopy {
public:
    Nocopy() = default;
    Nocopy(const Nocopy&) = delete;
    Nocopy& operator=(const Nocopy&) = delete;
    ~Nocopy() = default;
    //......
}

设计成友元能拷贝

class uncopyable {
protected:
    uncopyable() {}
    ~uncopyable() {}
private:
    uncopyable(const uncopyable&);
    const uncopyable& operator=(const uncopyable&);
}
<think>好的,我需要回答用户关于C++中=default=delete的用法及区别的问题。首先,我应该回顾一下这两个关键字的基本概念。根据用户提供的引用,=default用于显式要求编译器生成默认的函数实现,而=delete则是禁止编译器生成特定函数,或者禁用非成员函数,防止不期望的类型转换或调用。 接下来,我需要整理它们的应用场景。比如,当用户自定义了有参构造函数后,编译器不再生成默认构造函数,这时可以使用=default来恢复默认构造函数的生成。而对于=delete,常见的情况是禁用拷贝构造函数或拷贝赋值运算符,以防止对象被拷贝,这在管理资源时尤为重要,比如智能指针的实现。 然后,我需要区分两者的使用范围。根据引用[4],=delete可以用于任何函数,包括普通成员函数和非成员函数,而=default仅适用于编译器能够自动生成的默认特殊成员函数,如构造函数、析构函数、拷贝控制成员等。例如,用户可能希望禁止某个函数接受某些参数类型,这时可以使用=delete来删除特定的重载版本,避免隐式转换带来的问题。 还需要提到使用这两个关键字的好处。比如,使用=default可以保持代码的简洁,同时明确表达意图,而=delete则增强了代码的安全性,防止误用某些函数。引用[1]中提到,删除正常成员函数或非成员函数可以防止有问题的类型导致调用非预期的函数,比如禁用不需要的参数转换。 此外,需要结合具体的代码示例来说明两者的用法。比如引用[1]中的例子,类A定义了有参构造函数后,使用A() = default来生成默认构造函数。而如果希望禁用拷贝构造函数,可以声明其为=delete,这样编译器不会生成默认的拷贝构造,任何尝试拷贝该类的对象都会导致编译错误。 最后,我应该总结两者的主要区别,包括用途、适用范围和语法要求。确保用户能够清晰理解何时使用=default,何时使用=delete,以及它们如何帮助编写更安全、更高效的C++代码。</think>### C++中`=default`与`=delete`的用法及区别 #### 一、`=default`的用途 1. **显式生成默认函数** 当类中已定义其他构造函数(如带参构造函数),但需要保留默认构造函数时,可通过`=default`显式要求编译器生成默认实现。例如: ```cpp class A { public: A(int x) {} // 用户定义构造函数 A() = default; // 显式生成默认构造函数 }; ``` 此操作确保`A a;`能调用默认构造函数[^1]。 2. **适用于特殊成员函数** `=default`仅可用于编译器默认生成的函数,包括: - 默认构造函数 - 拷贝/移动构造函数 - 拷贝/移动赋值运算符 - 析构函数 示例: ```cpp class MyClass { public: MyClass() = default; // 默认构造函数 MyClass(const MyClass&) = default; // 拷贝构造函数 MyClass& operator=(const MyClass&) = default; // 拷贝赋值运算符 }; ``` 通过`=default`,可保持特殊成员函数的默认行为,同时允许其他自定义操作[^2]。 --- #### 二、`=delete`的用途 1. **禁用特殊成员函数** 用于阻止编译器生成默认实现,常见于禁用拷贝或移动操作。例如: ```cpp class NonCopyable { public: NonCopyable() = default; NonCopyable(const NonCopyable&) = delete; // 禁用拷贝构造 NonCopyable& operator=(const NonCopyable&) = delete; // 禁用拷贝赋值 }; ``` 此时尝试拷贝`NonCopyable`对象会引发编译错误,避免资源重复释放等问题[^3]。 2. **禁止特定函数调用** `=delete`还可用于普通成员函数或非成员函数,防止隐式类型转换或参数匹配问题。例如: ```cpp void process(int x) {} void process(double) = delete; // 禁止使用double参数调用 process(10); // 允许 process(3.14); // 编译错误 ``` 此用法可避免因类型转换导致的逻辑错误[^1]。 --- #### 三、关键区别总结 | **特性** | **`=default`** | **`=delete`** | |----------------|-----------------------------------------|-----------------------------------------| | **用途** | 显式生成默认函数实现 | 禁用函数生成或调用 | | **适用范围** | 仅限编译器可生成的默认特殊成员函数 | 任意函数(包括普通成员函数、非成员函数) | | **语法要求** | 需在函数声明末尾添加 | 可在函数声明或定义中使用 | | **典型场景** | 保留默认构造函数或拷贝控制语义 | 禁用拷贝、限制参数类型或特定重载 | --- #### 四、应用示例 1. **`=default`恢复默认行为** 当类需要同时支持自定义构造和默认构造时: ```cpp class B { public: B(int value) : data(value) {} B() = default; // 显式生成默认构造函数 private: int data = 0; }; ``` 2. **`=delete`防止隐式转换** 禁用不需要的构造函数重载: ```cpp class String { public: String(const char* str) {} String(char) = delete; // 禁止通过char类型构造 }; String s1("hello"); // 允许 String s2('a'); // 编译错误 ``` --- #### 五、优点总结 - **`=default`**:保持代码简洁,明确依赖编译器生成的默认逻辑,避免手动实现冗余代码[^4]。 - **`=delete`**:增强类型安全性,防止不合理的操作或参数转换,提升代码健壮性[^1]。 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值