【C++】构造函数冒号后面的初始化列表使用小括号( )和大括号{ }的区别(回子的四种写法)

news/2024/10/28 23:57:36/

1、创建对象时,使用小括号( )和大括号{ }的区别

1)内置类型的初始值,以下三种方法没有区别

int x(0); 
int y = 0;
int z{0}; 

2)自定义类型的赋值

Widget w1;       调用默认构造函数
Widget w2 = w1;  调用拷贝构造函数,不是赋值操作
w1 = w2;         调用operator=函数,是赋值操作

3)类内成员的默认初始值
类内成员的默认初始值:可以使用大括号、等号;不可以使用小括号

class Widget {...
private:int x{ 0 };   x的默认初始值为0int y = 0;    同上int z( 0 );   报错
}

注意:当大括号用于类内成员的默认初始值时,如果初始值存在丢失信息的风险,则编译器将报错:

doubel ld = 3.14;
int a {ld};    报错,存在信息丢失风险
int b (ld);    正确

4)声明对象还是创建对象
调用带参构造函数,可以使用如下方法:

Widget w1(10); 

如果想调用午餐构造函数时,不可以使用下面的方法,因为这会被编译器理解为:声明了个函数,而不是创建对象

Widget w2()

正确的方法:

Widget w2; 

或者使用大括号

Widget w2{}; 

2、大括号和std::initializer_list

大括号这么牛逼,统一都使用大括号不就得了。实际情况不是这么理想。这很C++……

1)先看使用 std::initializer_list 的情况(小括号和大括号行为一致)
大括号初始化的缺点是它有时会显现令人惊讶的的行为。这些行为的出现是因为与std::initializer_list混淆了。在构造函数中,只

class Widget {
public:Widget(int i, bool b);Widget(int i, double d);...
};Widget w1(10, true);   调用第一个构造函数
Widget w2{10, true};   调用第一个构造函数
Widget w3(10, 5.0);    调用第二个构造函数
Widget w4{10, 5.0};    调用第二个构造函数

2)形参带有std::initializer_list
如果构造函数的形参带有std::initializer_list,调用构造函数时大括号初始化语法会强制使用带 std::initializer_list 参数的重载构造函数:

class Widget {
public:Widget(int i, bool b);Widget(int i, double d);Widget(std::initializer_list<long double> il);...
};
Widget w1(10, true);    使用圆括号,调用第一个构造函数
Widget w2{10, true};    使用大括号,强制调用第三个构造函数,10true被转换为long double                    
Widget w3(10, 5.0);     使用圆括号,调用第二个构造函数
Widget w4{10, 5.0};     使用大括号,强制调用第三个构造函数,105.0被转换为long double

3)拷贝构造和赋值构造也受带有std::initializer_list的构造函数的影响

class Widget {
public:Widget(int i, bool b);Widget(int i, double d);Widget(std::initializer_list<long double> il);operator float() const;   // 支持隐式转换为float类型...
};Widget w5(w4);    使用圆括号,调用拷贝构造函数
Widget w6{w4};    使用大括号,调用第三个构造函数,原因是先把w4转换为float,再把float转换为long dobule
Widget w7(std::move(m4));  使用圆括号,调用移动构造函数
Widget w8{std::move(m4)};  使用大括号,调用第三个构造函数,理由同w6

4)即使参数数量不匹配,照样优先使用 std::initializer_list 的构造函数,

class Widget {
public:Widget(int i, bool b);Widget(int i, double d);Widget(std::initializer_list<bool> il);  // long double 改为 bool...
};Widget w{10, 5.0}; 

报错,因为参数个数不匹配,编译器会忽略另外两个构造函数(第二个还是参数精确匹配的!)

5)只有当大括号内的值无法转换为std::initializer_list元素的类型时,编译器才会使用正常的重载选择方法:

class Widget {
public:Widget(int i, bool b);Widget(int i, double d);Widget(std::initializer_list<std::string> il);  // bool 改为 std::string...
};Widget w1(10, true);   使用圆括号,调用第一个构造函数
Widget w2{10, true};   使用大括号,不过调用第一个构造函数,因为无法转换为string
Widget w3(10, 5.0);    使用圆括号,调用第二个构造函数
Widget w4{10, 5.0};    使用大括号, 不过调用第二个构造函数,因为无法转换为string

6)只有空括号可以不强制匹配 std::initializer_list 构造函数

class Widget {
public:Widget();Widget(std::initializer_list<int> il);...
};Widget w1;     调用默认构造函数
Widget w2{};   调用默认构造函数

7)小括号( )和大括号{ }初始化容器时的却

std::vector v1(10, 20); // 使用不带std::initializer_list的构造函数,创建10个元素的vector,每个元素的初始值为20
std::vector v2{10, 20}; // 使用带std::initializer_list的构造函数, 创建2个元素的vector,元素值为10和20

原因是:
std::vector中有一个可以指定容器的大小和容器内元素的初始值的不带std::initializer_list构造函数,但它也有一个可以指定容器中元素值的带std::initializer_list函数。


http://www.ppmy.cn/news/1542719.html

相关文章

【linux故障处理】【-bash: nginx: 未找到命令】

故障现象&#xff1a; [rootmini-71 nginx-1.24.0]# nginx -bash: nginx: 未找到命令 解决&#xff1a; # 打开环境变量配置文件 vim /etc/profile # 在文件末尾添加如下内容&#xff0c;指向nginx的安装目录 PATH$PATH:/usr/local/nginx/sbin # 重新加载使修改生效 so…

驾校小程序:一站式学车解决方案的设计与实践

​​一、引言 随着移动互联网技术的飞速发展&#xff0c;人们的生活方式和消费习惯正在发生深刻变化。驾校作为传统的服务行业&#xff0c;也面临着数字化转型的迫切需求。驾校小程序作为一种轻量级的应用&#xff0c;能够为用户提供便捷、丰富的学车服务&#xff0c;成…

Ubuntu20.04系统安装opencv

一、安装opencv 1、下载opencv-3.4.15数据包并解压 下载地址Release OpenCV 3.4.15 opencv/opencv GitHub 或官网下载地址 conda create -n opencv python3.8 conda activate opencv unzip opencv-3.4.15.zip 2、使用 cmake 安装 opencv 首先进入解压后的文件夹&…

构建中小企业设备管理平台:Spring Boot应用

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

【ios】---SwiftUI开发从入门到放弃

SwiftUI开发从入门到放弃 基本知识开发ios app1.打开Xcode&#xff0c;新建项目2.开发代码3.制作图标4.替换图标5.修改名称6.运行 Xcode界面 基本知识 与H5相对比 开发ios app 1.打开Xcode&#xff0c;新建项目 2.开发代码 import SwiftUI func mySelect() -> String {r…

leetcode hot100【LeetCode 104. 二叉树的最大深度】java实现

LeetCode 104. 二叉树的最大深度 题目描述 给定一个二叉树&#xff0c;找出其最大深度。 二叉树的深度为从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&am…

Linux基础命令(五) 之 cat,head,tail,more,less,grep

目录 一&#xff0c;浏览普通文件内容 二&#xff0c;过滤文件内容显示--grep 参数及其作用 ​编辑 常见用法 一&#xff0c;浏览普通文件内容 注意&#xff1a;以上命令均可以结合管道符一起使用 二&#xff0c;过滤文件内容显示--grep 在指定的普通文件中查找并显示含有…

三款PDF解密工具,轻松打开加密文档

分享三款PDF解密工具&#xff0c;操作简单&#xff0c;可以轻松上手。 1、PDF Candy 这个网站可以将文件转换为PDF和20多种格式。此外&#xff0c;PDF Candy提供47种在线工具来处理PDF:编辑、拆分、合并、压缩、解锁等等。 部分功能&#xff1a; PDF等文件格式转转换 PDF压缩…