只谈C++11新特性 - 删除函数

删除函数

背景

在 C++11 之前,C++ 的类默认会生成拷贝构造函数和赋值运算符。这在某些情况下会引发问题,尤其是在我们希望明确禁止某些操作时。假设我们有一个类,它不希望被拷贝,但未明确声明拷贝构造函数和赋值运算符,这时编译器会自动生成默认实现,导致程序员可能无意间拷贝了该类对象,造成不可预期的行为或运行时错误。

示例

cpp 复制代码
#include <iostream>

class NonCopyable {
public:
    NonCopyable() {}
    ~NonCopyable() {}
};

int main() {
    NonCopyable obj1;
    NonCopyable obj2 = obj1; // 未明确禁止拷贝,编译器生成默认的拷贝构造函数
    return 0;
}

上述代码中,NonCopyable 类没有声明拷贝构造函数,导致编译器生成了默认实现。而我们希望禁止对象的拷贝,却无法直接在编译时捕获这种问题。

常见的解决方案:将函数设为 private

在 C++11 之前,一个常见的解决方法是将不希望调用的拷贝构造函数和赋值运算符声明为 private,并且不提供实现。这样,尝试拷贝或赋值时会因访问权限问题导致编译错误。

cpp 复制代码
#include <iostream>

class NonCopyable {
public:
    NonCopyable() {}
    ~NonCopyable() {}

private:
    NonCopyable(const NonCopyable&); // 声明为 private,禁止拷贝
    NonCopyable& operator=(const NonCopyable&); // 声明为 private,禁止赋值
};

int main() {
    NonCopyable obj1;
    // NonCopyable obj2 = obj1; // 编译错误:拷贝构造函数是 private 的
    // obj1 = obj2;            // 编译错误:赋值运算符是 private 的
    return 0;
}

虽然这种方式能够达到禁止拷贝和赋值的目的,但它的缺点在于代码不够直观,而且容易因未实现的函数导致链接错误。


新特性:删除函数

C++11 引入了"删除函数"(Deleted Functions)的概念,它允许开发者显式地声明某些函数为"已删除",以禁止这些函数的调用。这一特性为类的设计提供了更精确的控制。

通过将函数声明为 = delete,编译器会在编译期检查是否存在对这些函数的调用,并在调用时产生编译错误。


删除函数的用途

禁止拷贝或赋值

通过删除拷贝构造函数和赋值运算符,可以明确禁止类的拷贝和赋值。

示例代码:禁止拷贝

cpp 复制代码
#include <iostream>

class NonCopyable {
public:
    NonCopyable() {}
    ~NonCopyable() {}

    // 禁止拷贝构造
    NonCopyable(const NonCopyable&) = delete;

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

int main() {
    NonCopyable obj1;
    // NonCopyable obj2 = obj1; // 编译错误:调用已删除的拷贝构造函数
    // obj1 = obj2;            // 编译错误:调用已删除的赋值运算符
    return 0;
}

删除函数的优点

  1. 显式性:代码更清晰,开发者可以直接通过声明了解哪些操作被禁止。
  2. 安全性:在编译时检测不正确的调用,避免运行时错误。
  3. 可读性 :比通过私有继承 boost::noncopyable 或声明私有拷贝构造函数的旧方式更直观。

总结

C++11 的删除函数为开发者提供了一种优雅且高效的方式来明确禁止特定操作,特别是在需要防止类的拷贝或赋值时。这一特性提升了代码的安全性和可读性,使得开发者能够更好地设计和维护复杂的 C++ 项目。


相关推荐
未秃头的程序猿4 小时前
一次重复扣款的复盘:分布式锁加错了维度,比不加锁更危险
java·redis·后端
张小姐的猫4 小时前
【MySQL】数据类型
android·linux·数据库·c++·mysql·adb·php
估值探索者4 小时前
【Python量化技术指标实战 02】MACD金叉也分强弱?手工算一次 DIF/DEA 就懂了
java·开发语言·python·股票数据·股票数据api接口
讳疾忌医丶4 小时前
编译器眼中的 C++ 循环:从指针别名、IEEE 754 结合律到 SIMD 语义证明
开发语言·c++
m0_639906944 小时前
MyBatis 核心体系:核心接口、动态 SQL 原理、插件底层机制
java·sql·mybatis
重生六道4 小时前
B站视频时长统计:一段JS脚本搞定分P/合集总时长(附倍速计算)
开发语言·javascript·音视频
XiYang-DING5 小时前
P5528.带过期时间的 LRU 缓存
java·开发语言·缓存
SimonKing5 小时前
DeepSeek 新模型免费白嫖,夯夯夯,赶紧用起来
java·后端·程序员
小徐不徐说5 小时前
C++ 机器视觉入门:从零搭建 AOI 开发环境(OpenCV + CMake)
开发语言·c++·opencv
SabrinaW7115 小时前
基于 C++17 与 RTTR 的注册式对象工厂:配置驱动的动态对象创建
java·前端·数据库