c++11:就地初始化与列表初始化

选自:

https://blog.csdn.net/K346K346/article/details/55194246

https://www.cnblogs.com/lsgxeva/p/7787245.html

还可以看看:

https://blog.csdn.net/lixiaogang_theanswer/article/details/82563961

1.就地初始化

1.1简介

在C++11之前,只能对结构体或类的静态常量成员进行就地初始化,其他的不行。

class C
{
private:
	static const int a=10;	//yes
	int a=10;					//no
}

在C++11中,结构体或类的数据成员在申明时可以直接赋予一个默认值,初始化的方式有两种,一是使用等号“=”,二是使用大括号列表初始化的方式。注意,使用参考如下代码:

class C    
{
private:  
    int a=7; 	//C++11 only
    int b{7}; //或int b={7}; C++11 only
    int c(7);	//error
};    

1.2就地初始化与初始化列表的先后顺序
C++11标准支持了就地初始化非静态数据成员的同时,初始化列表的方式也被保留下来,也就是说既可以使用就地初始化,也可以使用初始化列表来完成数据成员的初始化工作。当二者同时使用时,并不冲突,初始化列表发生在就地初始化之后,即最终的初始化结果以初始化列表为准。参考如下代码:

#include <iostream>
using namespace std;

class Mem
{
public:
	Mem(int i,int j):m1(i),m2(j) {}

	int m1 = 1;
	int m2 = {2};
};

int main()
{
	Mem mem(11,22);
	cout<<"m1="<< mem.m1<<" m2="<<mem.m2<<endl;
}

m1=11 m2=22

2.列表初始化

C++11之前主要有以下几种初始化方式:

//小括号初始化
string str("hello");

//等号初始化
string str="hello";

//POD对象与POD数组列表初始化
struct Studnet
{
	char* name;
	int age;
};
Studnet s={"dablelv",18}; //纯数据(Plain of Data,POD)类型对象
Studnet sArr[]={{"dablelv",18},{"tommy",19}};  //POD数组

//构造函数的初始化列表
class Class
{
	int x;
public:
	Class():x(0){} 
};

这么多的对象初始化方式,不仅增加了学习成本,也使得代码风格有较大出入,影响了代码的可读性和统一性。从C++11开始,对列表初始化(List Initialization)的功能进行了扩充,可以作用于任何类型对象的初始化,至此,列表初始化方式完成了天下大一统。

class Test
{
    int a;
    int b;
public:    
    C(int i, int j);    
};    
Test t{0,0};                   //C++11 only,相当于 Test t(0,0);    
Test* pT=new Test{1,2};        //C++11 only,相当于 Test* pT=new Test{1,2};
int* a = new int[3]{1,2,0};   	//C++11 only

此外,C++11列表初始化还可以应用于容器,终于可以摆脱 push_back() 调用了,C++11中可以直观地初始化容器:

//C++11 container initializer
vector<string> vs={"first", "second", "third"};
map<string,string> singers ={{"Lady Gaga", "+1 (212) 555-7890"},{"Beyonce Knowles", "+1 (212) 555-0987"}};

因此,可以将C++11提供的列表初始化作为统一的初始化方式,既降低了记忆难度,也提高的代码的统一度。

————————————————
版权声明:本文为CSDN博主「Dablelv」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/K346K346/article/details/55194246

 

C++11 初始化

统一初始化语法
        C++11新添加初始化列表 std::initializer_list<>类型,可以通过{}语法来构造初始化列表 。初始化列表是常数;一旦被创建,其成员均不能被改变,成员中的数据也不能够被变动。函数能够使用初始化列表作为参数。
        在引入C++ 11之前,有各种不同的初始化语法。在C++ 11中,仍可以使用这些初始化语法,但也可以选择使用新引入的统一的初始化语法。统一的初始化语法用一对大括号{}表示。
        std::vector<string> v1 = {"hello", "world", "welcome"};
        std::vector<int> v2 = {0, 3, 8, 1, 4};

// 注: vs2012 不支持统一初始化方式{}

类内成员初始化

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <vector>
#include <map>

class Mem
{
public:
    Mem(int i, int j): m(i), n(j) // 初始化列表给m初始化, 可以给const变量赋初值, 以及引用变量赋初值
    {
        // m = i; 错误,不能给const变量赋值
        // n = j; 错误,不能给引用变量赋值
    }
    int getM()
    {
        std::cout << "m: " << m << std::endl;
    }
    const int m;
    int &n;
};


void mytest()
{
    int data = 1; // 使用"="初始化非静态普通成员,也可以 int data{1};
    Mem Mem{2, data}; // 对象成员,创建对象时,可以使用{}来调用构造函数 // 注: vs2012 不支持统一初始化方式{}
    std::string name("xyz"); // 使用()来调用构造函数

    return;
}

int main()
{
    mytest();

    system("pause");
    return 0;
}

列表初始化
C++11引入了一个新的初始化方式,称为初始化列表(List Initialize),具体的初始化方式如下:

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <vector>
#include <map>

class Person
{
public:
    std::string name;
    int age;
};

void mytest()
{
    int a[] = {4,5,6};
    int b[]{1,3,5}; // 注: vs2012 不支持
    int i = {1};
    int j{3}; // 注: vs2012 不支持

    // 初始化列表可以用于初始化结构体类型
    Person p1 = {"Frank", 25};

    std::vector<int> ivec1(3,4);
    // 其他一些不方便初始化的地方使用,比如std<vector>的初始化,如果不使用这种方式,只能用构造函数来初始化,难以达到效果
    std::vector<int> ivec2 = {5,5,5}; // 注: vs2012 不支持
    std::vector<int> ivec3 = {1,2,3,4,5}; // 注: vs2012 不支持

    return;
}

int main()
{
    mytest();

    system("pause");
    return 0;
}

防止类型收窄
类型收窄指的是导致数据内容发生变化或者精度丢失的隐式类型转换。使用列表初始化可以防止类型收窄。

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <vector>
#include <map>


void mytest()
{
    const int x = 1024;
    const int y = 10;

    char a = x; // 收窄,但可以通过编译
    char *b = new char(1024); // 收窄,但可以通过编译

    char c = {x}; // err,收窄,无法通过编译
    char d = {y}; // 可以通过编译
    unsigned char e{-1}; // err,收窄,无法通过编译

    float f{7}; // 可以通过编译
    int g{2.0f}; // err,收窄,无法通过编译
    float * h = new float{1e48}; // err,收窄,无法通过编译
    float i = 1.21; // 可以通过编译

    return;
}

int main()
{
    mytest();

    system("pause");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值