网站首页 > 基础教程 正文
当存在用户自定义构造函数时,禁止集合初始化,澄清相关细节
集合初始化是针对集合类(aggregate)的初始化方法,使用大括号进行初始化,主要不要和列表初始化进行混淆。列表初始化同样是使用大括号进行初始化。但集合初始化是直接对成员变量进行初始化,而列表初始化是使用构造函数的。
集合类是有要求的:
- 没有私有或者保护的非静态成员变量
- 没有用户自定义或者继承的构造函数
- 没有虚基类、私有基类、保护基类
- 没有虚函数
C++ 17 标准中已经有了对“没有自定义构造函数“的要求,但要求不够完善,因此出现很多不合理的问题,所以在 C++ 20 中进行了修正。
例子(1):
struct SA
{
SA() = delete;
};
SA a1; // <1> Error,编译不通过,因为默认构造函数被删除,所以不能构造
SA a2 { }; // <2> Error,同上,但C++17可以编译通过!因此C++20修正为编译不通过
当默认构造函数被删除,语句<1>编译不通过,这是很合理的。同样的,语句<2>也是应该编译不通过的。但按照以前的理解,集合类要求没有声明用户自定义的构造函数,那么将默认构造函数删除,算不算用户自定义了构造函数呢?
以前的标准认为是不算,因为确实没有生成新的用户自定义构造函数。但这样语句<1>和语句<2>的差异也不合理。所以后来标准改为,只要是有默认构造函数的相关声明,新增或者删除,或者是保持default,都不能进行集合初始化。
例子(2):
struct SA
{
private:
SA() = default;
};
SA a1; // <1> Error,编译不通过,因为默认构造函数是私有的,所以不能构造
SA a2 { }; // <2> Error,同上,但C++17可以编译通过!因此C++20修正为编译不通过
将默认构造函数改为私有,也不能进行集合初始化。
例子(3):
struct SA
{
int m_a { 4 };
SA() = default;
};
SA a1; // <1> OK,构造函数不带参数,然后根据定义时的默认值进行赋值
SA a2 { 5 }; // <2> Error,更改了默认值,但C++17可以编译通过!因此C++20修正为编译不通过
上述例子中,显式定义了不带参数的构造函数,那么就是不应该允许有参数的构造方式,因此集合初始化也不应该有效。
例子(4):
struct SA
{
int m_a { 4 };
SA( int ) = delete;
};
SA a1 ( 3 ); // <1> Error,删除了int参数的构造函数,就是显式要求不允许使用int参数进行初始化
SA a2 { 5 }; // <2> Error,应该同上,但C++17可以编译通过!因此C++20修正为编译不通过
和上面的例子类似,更直观一些,直接将int参数的构造函数删除,就不应该支持通过int参数来进行初始化,所以要将集合初始化也改为禁止,保持行为一致。
例子(5):
struct SA
{
int m_a ;
SA( int ) = default;
};
struct SC
{
int m_a ;
SC( int );
};
SC::SC() = default;
SA a1 { 3 }; // <1> C++17 编译通过
SC c1 { 3 }; // <2> C++17 编译不通过
对于这个例子,SA和SC的构造函数是一样的,只不过是直接在类里面定义,还是在类外面定义而已,但C++17的认为这两种情况有区别,一个能编译通过,另一个编译不通过。但这样的差异是不合理的。
因此,在 C++ 20 中,对这些情况都进行了统一,将是否有用户自定义构造函数的标准放宽,只要是有构造函数相关的声明,不管是新增还是删除,还是维持default,都认为是有用户自定义构造函数,都禁止使用集合初始化。(但使用大括号的列表初始化还是支持,不过这时候不是直接对成员变量初始化,还是根据构造函数来初始化)
【往期回顾】
- 上一篇: 小白学编程,C++ 初始化的坑,你避开了吗?
- 下一篇: c++数组初始化的三种方式#野牛程序员
猜你喜欢
- 2024-10-10 C++系列1-1:初探C++ c=2μf
- 2024-10-10 浅谈C++11(第9篇 可变参数模板) c++可变参数模板类
- 2024-10-10 数组的初始化方式有哪几种? 数组的初始化是什么意思
- 2024-10-10 c++对于内建类型的默认初始化 创建内部类的对象
- 2024-10-10 C++类构造函数,如何初始化对象?linux C++第27讲
- 2024-10-10 【C++编程语言】之 类和对象——对象的初始和消除
- 2024-10-10 C++基础语法梳理:引用、封装、继承和多态
- 2024-10-10 C++核心准则?:按照成员声明的顺序定义和初始化成员变量
- 2024-10-10 C++核心准则C.47:按照成员变量声明的次序定义和初始化数据成员
- 2024-10-10 C/C++语言编程系列002——不同情况下数组的初始化方法
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)