cpp 11&14 统一初始化方式以及initializer_list,for

  • 一致初始化
    1
    2
    3
    4
    5
    6
    int values[]{1,2,3};
    vector<int> v{1,2,3,4,5};
    vector<string> cities{
    "Berlin","New York"
    }
    complex<double> c{3.0,4.0}
  • initializer_list
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    //***********************//
    //initializer_list 传递的是引用,拷贝是浅拷贝
    //***********************//

    {1,2,3}// 会被编译器构造成一个initializer_list
    //如果函数只接收initializer_list 则调用者要自己准备一包initializer_list,来使用
    //如果目标函数不接受initializer_list,会被编译器分开来传入
    int i;//i的值是未定义
    int j{};//设置初值为0
    int* p;//未定义初值
    int* q{};//设置初值为nullptr
    int x1(5.3); // x1=5
    int x2 = 5.3;//x2=5
    int x3{5.0};//Error:narrowing ||-> GCC Warning
    int x4 ={5.3}; // Error:narrowing ||-> GCC Warning
    char c1{7};//ok
    char c2{99999};//Error:narrowing ||-> GCC Warning
    std::vector<int> v1{1,2,3,4,5};//ok
    std::vector<int> v1{1,2,3,4,5.5};//Error:narrowing ||-> GCC Warning

    max({stirng("Ace"),string("Stacy"),stirng("qqq"),string("ppp")}) //函数可以接收initializer_list,作为入参
    min({1,2,3,4})//函数可以接收initializer_list,作为入参

    cpp 11&14 统一初始化方式以及initializer_list

    一致初始化

    code

    1
    2
    3
    4
    5
    6
    int values[]{1,2,3};
    vector<int> v{1,2,3,4,5};
    vector<string> cities{
    "Berlin","New York"
    }
    complex<double> c{3.0,4.0}

initializer_list

接受任意个参数,但类型要相同

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

//***********************//
//initializer_list 传递的是引用,拷贝是浅拷贝
//***********************//

int i;//i的值是未定义
int j{};//设置初值为0
int* p;//未定义初值
int* q{};//设置初值为nullptr
int x1(5.3); // x1=5
int x2 = 5.3;//x2=5
int x3{5.0};//Error:narrowing ||-> GCC Warning
int x4 ={5.3}; // Error:narrowing ||-> GCC Warning
char c1{7};//ok
char c2{99999};//Error:narrowing ||-> GCC Warning
std::vector<int> v1{1,2,3,4,5};//ok
std::vector<int> v1{1,2,3,4,5.5};//Error:narrowing ||-> GCC Warning

sample 正确

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class P{
public:
P(int a,int b){
cout<<"P(int,int),a="<<a<<" b="<<b<<endl;
}
P(initializer_list<int> initlist){
cout<<"P(initializer_list<int>),values=";
for(auto i:initializer_list){
cout<<i<<" "
}
cout<<endl;
}
}

P p(77,5);//P(int,int);
P q{77,4};//P(initializer_list<int>); 形成一包,所以调用的是P(initializer_list<int>)
P r{77,5,42};//P(initializer_list<int>);
P s={77,5};//P(initializer_list<int>);

sample 错误

1
2
3
4
5
6
7
8
9
10
11
class P{
public:
P(int a,int b){
cout<<"P(int,int),a="<<a<<" b="<<b<<endl;
}
}

P p(77,5);//P(int,int);
P q{77,4};//P(int,int);
P r{77,5,42};//Error
P s={77,5};//P(initializer_list<int>);

explicit 当构造函数含有多个入参时

explicit 应用在只有一个参数在构造函数时
old version
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//*******************************
// 隐含调用含有一个参数的构造函数
struct Complex
{
int real,imag;
Complex(int re,int im=0):real(re),imag(im){}
Complex operator+(const Complex& x)
{
return Complex((real+x.real),(imag+x.imag))
}
}
Complex c1(12,5);
Complex c2=c1+5;// 隐含调用含有一个参数的构造函数

//***************************
//禁止隐含调用构造,除非明确指出
struct Complex
{
int real,imag;
Complex(int re,int im=0):real(re),imag(im){}

explicit
Complex operator+(const Complex& x)
{
return Complex((real+x.real),(imag+x.imag))
}
}
Complex c1(12,5);
//禁止隐含调用构造,除非明确指出
Complex c2=c1+5;// Erorr no match for 'operator+'
c11 version
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
```

```cpp
class P{
public:
P(int a,int b){
cout<<"P(int,int),a="<<a<<" b="<<b<<endl;
}
P(initializer_list<int> initlist){
cout<<"P(initializer_list<int>),values=";
for(auto i:initializer_list){
cout<<i<<" "
}
cout<<endl;
}
explicit
P(int a,int b,int c){
cout<<"P(int,int),a="<<a<<" b="<<b<<endl;
}
}

void fp(const P&){};

P p(77,5);//P(int,int);
P q{77,4};//P(initializer_list<int>); 形成一包,所以调用的是P(initializer_list<int>)
P r{77,5,42};//P(initializer_list<int>);
P s={77,5};//P(initializer_list<int>);
//Error ****************//
P p5 = {77,88,3}//Error converting to 'p' from initilizer list would use explicit constructor
//Error ****************//
P p6 = {77,88,3,8}//P(initializer_list<int>);

fp({11,22})//P(initializer_list<int>)
//Error ****************//
fp({47,11,3})//Error converting to 'const p' from initilizer list would use explicit constructor
//Error ****************//
fp(P{47,11})//P(initializer_list<int>)
fp(P{26,11,3}) //P(initializer_list<int>)

技术实现细节

array 容器的TR1(版本)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <typename _Tp,std::size_t _Nm>
struct array
{
typedef _Tp value_type;
typedef _Tp* pointer;
typedef value_type* iterator;
//Support for zero-sized arrays mandatory;
value_type _M_instance[_Nm?_Nm:1];
iterator begin(){return iterator(&_M_instance[0]);}
iterator end(){return iterator(&_M_instance[_Nm]);}
}

//使用
array<int,10> myArray;

initializer_list的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// std::initializer_list support -*- C++ -*-

// Copyright (C) 2008-2022 Free Software Foundation, Inc.
//
// This file is part of GCC.



// gcc/libstdc++-v3/libsupc++/initializer_list


#ifndef _INITIALIZER_LIST
#define _INITIALIZER_LIST

#pragma GCC system_header

#if __cplusplus < 201103L
# include <bits/c++0x_warning.h>
#else // C++0x

#pragma GCC visibility push(default)

#include <bits/c++config.h>

namespace std
{
/// initializer_list
template<class _E>
class ##### TR1(版本)
```cpp
template <typename _Tp,std::size_t _Nm>
struct array
{
typedef _Tp value_type;
typedef _Tp* pointer;
typedef value_type* iterator;
//Support for zero-sized arrays mandatory;
value_type _M_instance[_Nm?_Nm:1];
iterator begin(){return iterator(&_M_instance[0]);}
iterator end(){return iterator(&_M_instance[_Nm]);}
}

//使用
array<int,10> myArray;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{
public:
typedef _E value_type;
typedef const _E& reference;
typedef const _E& const_reference;
typedef size_t size_type;
typedef const _E* iterator;
typedef const _E* const_iterator;

//**********************************************//
// 实现是依靠array 容器
private:
iterator _M_array;
size_type _M_len;
//**********************************************//




//**********************************************//
// The compiler can call a private constructor.
// 当编译器看到{}时会调用下面的的构造,在调用initializer_list构造函数之前
// 编译器会先创建一个array容器,后会将array的容器的迭代器和长度,传入initializer_list 构造函数
//**********************************************//
constexpr initializer_list(const_iterator __a, size_type __l)
: _M_array(__a), _M_len(__l) { }

public:
constexpr initializer_list() noexcept
: _M_array(0), _M_len(0) { }

// Number of elements.
constexpr size_type
size() const noexcept { return _M_len; }

// First element.
constexpr const_iterator
begin() const noexcept { return _M_array; }

// One past the last element.
constexpr const_iterator
end() const noexcept { return begin() + size(); }
};

for 新的写法

使用引用可以使遍历更加快速,同时可以修改变量的值

关联式容器不可以修改值

  • set
  • map
  • unorder_set
  • unorder_map
  • multiset
  • multimap

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14

vector<double> vec;
for(auto s:vec){
cout<<s<<endl;
}
// 赋值速度更快,同时可以修改其中的值
for(auto& s:vec){

s*=3;
}
for(const auto& s:vec){
cout<<s<<endl;
}

实现

1
2
3
4
5
6
7
8
9
vector<double> vec;
for(auto s:vec){
cout<<s<<endl;
}

for(auto _pos=coll.begin(),_end=end(doll);_pos!=_end;++_pos){
decl=*_pos;
//statement(cout<<s<<endl;)
}

转型实现

1
2
3
4
5
6
7
8
9
10
11
12
13

class C{
public:
explicit C(const stirng& s); //禁止自动转换

};

vector<string> vs;
for(const C& elem:vs){ // Error,no conoversion from string to C defined
// 类型不同时,会进行默认的类型转换
cout<<elem<<endl;
}