C++:75---C++11标准(一致性初始化、初值列:initializer_list)

一、列表初始化/一致性初始化

  • 设计的目的:
    • 在C++11之前,如何初始化一个变量或对象的概念比较混淆。初始化的场景可以发生在:小括号、大括号或赋值操作符中
    • C++11引入了“列表初始化/一致性初始化”,意思为:面对任何初始化动作,你可以使用相同语法,就是使用大括号
  • 例如下面的都是正确的:
int units_sold = 0;
int units_sold = { 0 };
int units_sold{ 0 };
int units_sold(0);

int values[]{ 1,2,3 };

std::vector<int> v{ 2,3,5,7,11,13,17 };

std::vector<std::string> cites{
    "Berlin","New York","London"
}

局部基础数据类型的默认初始化

  • 对于局部变量的定义,如果我们没有给出初始值,那么这个变量定义的值是不明确的未知的
  • 如果我们使用{}对普通数据类型的变量进行定义,即使没有给出初始值,那么会根据数据类型进行默认初始化
  • 例如:
int i;    //乱值
int j{};  //0

int *p;   //p指向未知地址
int *q{}; //q为nullptr

禁止窄化

  • “窄化”意为:精度降低或造成数值变动
    • 对于一般的赋值与初始化,允许窄化的发生
    • 对于大括号的初始化,其不允许窄化的发生,如果有,那么编译将不通过。主要的原因是为了防止数据在转换中的丢失
  • 例如:
int x1(5.3);   //正确,允许double向int转变,但是x1为5
int x2 = 5.3;  //正确,同上
int x3{ 5.3 }; //错误,不允许,因为造成了数据丢失

char c1{ 7 };     //正确,7也属于char
char c2{ 99999 }; //错误,99999不属于char的范围,不允许转换

std::vector<int> v1{ 1,2,3,4,5 }; //正确
std::vector<int> v2{ 1.2,8,1.5 }; //错误,其中含有double数据

 

二、std::initializer_list

  • 为了支持“用户自定义类型之初值列”概念,C++11提供了class template std::initializer_list<>,用来支持以一些列值进行初始化
  • initializer_list在另一篇文章中已经介绍过,可以参阅:https://blog.csdn.net/qq_41453285/article/details/91895105
  • 本文就不详细介绍语法了,介绍一些演示案例,语法参阅上面的链接

一些演示案例

  • std::initializer_list提供begin()和end()两个成员。例如:
void print(std::initializer_list<int> vals)
{
    for (auto p = vals.begin(); p != vals.end(); ++p)
        std::cout << *p << std::endl;
}

print({ 12,3,5,4,8 });
  • 在类的构造函数使用std::initializer_list。例如:
class P {
public:
    P(int, int);
    P(std::initializer_list<int>);
};

int main()
{
    P p(77, 5);      //调用给P(int, int)
    P p2(77, 5, 20); //错误,

    P p3{ 77,5 };       //调用P(std::initializer_list<int>)
    P p4 = { 77,5 };    //调用P(std::initializer_list<int>)
    P p5{ 77,5,10,15 }; //调用P(std::initializer_list<int>)

    return 0;
}

//备注,如果P没有提供P(std::initializer_list<int>),那么上面的p3、p4将
//调用P(int, int),p5初始化将错误
  • explicit将抑制类的构造函数转换行为。例如:
class P {
public:
    P(int, int);
    explicit P(int, int, int);
};

int main()
{
    P p(77, 5);      //正确,调用P(int, int)
    P p2(77, 5, 20); //正确,调用explicit P(int, int, int)
    P p4 = { 77,5 }; //正确,调用P(int, int)

    //错误,explicit关键字抑制initializer_list列表使用P(int, int, int)构造函数
    P p4 = { 77,5,10 };
    
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董哥的黑板报

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值