首页 > 编程语言 >C++ 合成3/5法则时可能定义为删除的情况

C++ 合成3/5法则时可能定义为删除的情况

时间:2024-09-06 14:14:25浏览次数:9  
标签:法则 定义 删除 C++ 运算符 拷贝 移动 构造函数

如果我们未定义拷贝控制成员,编译器会为我们合成;如一个类未定义构造函数,编译器会为我们合成一个默认的构造函数。

合成拷贝控制成员可能是删除的情况:

  1. 如果类中有成员的析构函数是删除的或不可访问的(private):
    a. 则类的合成析构函数被定义为删除的;
    b. 则合成拷贝构造函数被定义为删除的;
    c. 若类内有引用成员没有类内初始化器,或类内有一个const成员没有类内初始化器,
    且其类型未显式的定义默认构造函数,则该类的默认构造函数被定义为删除的。

  2. 如果类中有成员的拷贝函数是删除的或不可访问的(private):
    a. 则类的合成拷贝函数被定义为删除的;

  3. 如果类中有成员函数的赋值运算符是删除的或不可访问的(private),
    或类有一const的或引用成员:
    a. 则类的合成拷贝赋值运算符被定义为删除的。

移动操作

与拷贝操作不同,移动操作永远不会隐式定义为删除的函数。但是,如果我们显式地要求编译器生成=default 的 (参见 7.1.4节,第 237 页)移动操作,且编译器不能移动所有成员,则编译器会将移动操作定义为删除的函数。
除了一个重要例外,什么时候将合成的移动操作定义为删除的函数遵循与定义删除的合成拷贝操作类似的原则(参见 13.1.6节,第 449 页):

  • 与拷贝构造函数不同,移动构造函数被定义为删除的函数的条件是:有类成员定义了自己的拷贝构造函数且未定义移动构造函数, 或者是有类成员未定义自己的拷贝构造函数且编译器不能为其合成移动构造函数。移动赋值运算符的情况类似。

  • 如果有类成员的移动构造函数或移动赋值运算符被定义为删除的或是不可访问的,则类的移动构造函数或移动赋值运算符被定义为删除的。

  • 类似拷贝构造函数,如果类的析构函数被定义为删除的或不可访问的,则类的移动构造函数被定义为删除的。

  • 类似拷贝赋值运算符,如果有类成员是const的或是引用,则类的移动赋值运算符被定义为删除的。

只有当一个类没有定义任何自己版本的拷贝控制成员,且类的每个非 static 数据成员都可以移动时,编译器才会为它合成移动构造函数或移动赋值运算符。编译器可以移动内置类型的成员。
如果一个成员是类类型,且该类有对应的移动操作,编译器也能移动这个成员。// 如果定义了拷贝构造函数,就不会再生成默认的移动拷贝了。

移动操作和合成的拷贝控制成员间还有最后一个相互作用关系:一个类是否定义了自己的移动操作对拷贝操作如何合成有影响。如果类定义了一个移动构造函数和/或一个移动赋值运算符,则该类的合成拷贝构造函数和拷贝赋值运算符会被定义为删除的。




摘自《C++ Primer》

标签:法则,定义,删除,C++,运算符,拷贝,移动,构造函数
From: https://www.cnblogs.com/huvjie/p/18400134

相关文章

  • 信奥赛C++老师解一本通题:1938:【07NOIP普及组】奖学金
    ​【题目描述】某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排......
  • 信奥赛C++老师解一本通题: 1180:分数线划定
    ​ 【题目描述】世博会志愿者的选拔工作正在A市如火如荼的进行。为了选拔最合适的人才,A市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的150%划定,即如果计划录取m名志愿者,则面试分数线为排名第m×150%(向下取整)名的选手......
  • 怎样用c++实现一个vector类
    给定的任务是用C++实现一个类,这个类的行为要和标准库中的Vector类一样。向量(Vector)就像动态数组一样,当插入或删除一个元素时,它能够自动调整自身大小,其存储由容器自动管理。vector中的元素被放置在连续的存储空间中,这样就可以使用迭代器来访问和遍历它们。在向量中,数据是在末尾插......
  • 代码随想录算法训练营第十天| 232.用栈实现队列 、 225. 用队列实现栈 、20. 有效的括
    学习文章链接:代码随想录文章目录一、232.用栈实现队列二、225.用队列实现栈三、20.有效的括号四、1047.删除字符串中的所有相邻重复项一、232.用栈实现队列题目链接:232.用栈实现队列栈的操作:stack<int>s;s.empty();//如果栈为空则返回true,......
  • 【C++编程题】格雷码与自然二进制码转换
        格雷码是数字信号处理中常用编码方式。格雷码中任意两个相邻代码的二进制位中只有一位不同,对于最大编码和最小编码也成立。1.异或法转换1.1二进制码转格雷码二进制码转格雷码[1]1)将二进制最高位保留;2)对于二进制码中剩余的任意第i位,将其与......
  • 《C++编程规范》五、类的设计与继承
    目录第32条弄清所要编写的是哪种类第32条弄清所要编写的是哪种类了解自我:有很多种不同的类。弄清楚要编写的是哪一种。不同种类的类适用于不同用途,因此遵循着不同的规则。值类(如std::pair,std::vector)模仿的是内置类型。一个值类应该:有一个公用析构函数、复制构造函......
  • C++ STL map/multimap容器
    map/multimap容器Map的特性是,所有元素都会根据元素的键值自动排序。Map所有的元素都是pair,同时拥有实值和键值,pair的第一个元素被视为键值,第二个元素被视为实值,map不允许两个元素有相同的键值。multimap和map的操作类似,唯一区别是multimap的键值可以重复。注意:Map和multimap都......
  • C++(lambda)
    目录1.语法2.示例3.捕获方式4.可变性(mutable关键字)5.Lambda表达式的用途总结C++中的lambda表达式是一种匿名函数,通常用于简化代码,尤其是在处理临时或小型回调函数时。Lambda表达式引入于C++11,并在之后的C++标准中不断增强。它们可以捕获上下文中的变量,生成临时的函数对象......
  • 【C++】vector有关代码
     C++代码:#include<iostream>#include<vector>intmain(){//创建一个整数类型的vector并初始化std::vector<int>v={1,2,3};//使用迭代器遍历并打印vector中的每个元素for(autoi=v.begin();i!=v.end();++i){std::c......
  • C++ STL set/multiset容器
    set/multiset容器简介Set的特性是,所有元素都会根据元素的值自动被排序。Set不允许两个元素有相同的值。Set的迭代器iterator是一种const_iterator,不能通过迭代器改变任意set元素的值。multiset的特性和用法和set相同,唯一的差别在于它允许值重复。set和multiset的底层实现是红......