• C++11——“=default“和“=delete“函数特性


    c++的类有四种特殊成员函数:

    • 默认构造函数
    • 析构函数
    • 拷贝构造函数
    • 拷贝赋值运算符

    ​ 这些类的特殊成员函数负责创建、初始化、销毁或者拷贝类的对象。
    ​ 如果程序员没有显示的为类定义某个特殊成员函数,而又需要用到该特殊成员函数时,编译器会隐式地为这个类生成一个默认的特殊成员函数;
    ​ 而如果程序员显示的定义了某个特殊成员函数,编译器将不会自动为你生成默认的构造函数了,如果还想用默认构造函数,就需要自己手写,如果变量很多的话这将会很麻烦。

    ​ c++11标准因此引入了新特性:default函数。程序员只需在函数声明后加上”=default;”,就可将该函数声明为defaulted函数,编译器将为显式声明的defaulted函数自动生成函数体。

    ​ defaulted函数特性仅适用于类的特殊成员函数,且该特殊成员函数没有默认参数。
    ​ defaulted函数既可以在类体里(inline)定义,也可以在类体外(out-of-line)定义。

    default的用处

    来看一个简单的例子:

    例子来源

    class Student
    {
    int ID;
    std::string sName;
    };
    
    Student s1;
    Student s2(s1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在不定义任何构造函数的情况下,Student对象能定义成功,因为编译器会默认为我们设置几个构造函数,多的不说了,就说最简单的两个

    Student() {}
    Student(const Student& o):ID(o.ID),sName(o.sName)
    {}
    
    • 1
    • 2
    • 3

    一个是在不提供任何参数的情况下的默认构造函数,另一个是通过另一个对象构造的拷贝构造函数

    class Student
    {
    int ID;
    std::string sName;
    public:
    Student(const string& _sName):sName(_sName){}
    };
    
    Student s1;
    Student s2(s1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    但是如果我们自己加了一个只指定名字参数的构造函数,上面这段代码就编译不过了。因为编译器就不自动为你生成默认的那些构造函数了,因为它觉得你想根据自己的需求定义构造函数。但是,如果你除了自己自定义的构造函数,还想用编译器为你生成默认的,怎么办?

    class Student
    {
    int ID;
    std::string sName;
    public:
    Student() {}
    Student(const Student& o) :ID(o.ID), sName(o.sName)
    {}
    Student(const string& _sName):sName(_sName){}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    传统的办法就是受点累,把编译器为你生成的那两个你亲自写一遍,这样不累吗?尤其是student成员变量很多的时候。有了default关键以后,省事多了,

    class Student
    {
        int ID;
        std::string sName;
        public:
        Student() = default;
        Student(const Student& o) = default;
        Student(const string& _sName):sName(_sName){}
    };
    
    Student s1;
    Student s2(s1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    那两个默认的构造函数,我们想要的实现跟编译器默认的一模一样,直接指定个default就行了,不用全部手打出来。这就是default这个关键字的作用。

    完整的例子如下所示:

    class x2
    {
        public:
        	x2() = default;	//inline(类内) defaulted 默认构造函数
        	x2(const x2&);
        	x2& operator=(const x2&);
        	~x2() = default;	//inline(类内) defaulted 析构函数
    };
    
    x2::x2(const x2&) = default; // 类外 拷贝构造函数
    x2& x2::operator=(const x2&) =default;	//类外 拷贝赋值操作符
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    delete的用处

    同样的对于上面的例子中,如果你不想让诸如:

    Student s1;
    Student s2(s1);
    
    • 1
    • 2

    这样的默认构造函数被调用,除了写显示的特殊函数,让编译器为你排除掉,还可以通过=delete函数特性来为你禁用某些函数

    例如:

    class x5
    {
        public:
        	// 禁用类的new操作符
        	void *operator new(size_t) = delete;
        	void *operator new[](size_t) = delete;
    }
    
    x5 *pa = new x5; // 错误
    x5 *pb = new x5[10]; // 错误
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    C++ 20 并发编程 std::promise
    ORDER BY clause is not in SELECT list
    【五、Ubuntu移植WiringPi库】
    Kubernetes(K8S第三部分之资源控制器)
    python列表合并,去重
    无涯教程-JavaScript - IMCSCH函数
    路飞day2
    Ansible Automation Platform - 导入外部主机清单
    java常见锁策略与CAS
    Springboot+redis序列化方式到底怎么选+redis配置类+redis工具类
  • 原文地址:https://blog.csdn.net/m0_56722204/article/details/128088856