欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++11/14学习(四)初始化列表

程序员文章站 2022-03-21 21:08:50
一. 传统C++ 传统 C++中,普通数组、没有构造析构和虚函数的类或结构体都可以使用 {} 进行初始化,也就是我们所说的初始化列表。而对于类对象的初始化,要么需要通过拷贝构造、要么就需要使用 () 进行,不支持{}。 int arr[3] = { 1,2,3 }; // 列表初始化class Fo... ......
一. 传统C++

传统 C++中,普通数组、没有构造析构和虚函数的类或结构体都可以使用 {} 进行初始化,也就是我们所说的初始化列表。
而对于类对象的初始化,要么需要通过拷贝构造、要么就需要使用 () 进行,不支持{}。

int arr[3] = { 1,2,3 }; // 列表初始化
class Foo
{
private:
    int value;
public:
    Foo(int) {}
};
Foo foo(1); // 普通构造初始化

二. 初始化列表

为了解决上面的问题,C++11把初始化列表的概念绑定到了类型上,并将其称之为 std::initializer_list 。
以下写法在C++11中都是被允许的:

int static_arr[5] = { 1, 2, 3, 4 };
int static_arr2[]{ 1, 2, 3, 4 }; // 等号要以省略
int* dynamic_arr = new int[5]{ 1, 2, 3, 4 };
vector<int> stl_vec{ 1, 2, 3, 4 };
set<int> stl_set{ 1, 2, 3, 3 };
map<const char*, int> stl_map
{
    { "Alice", 1 },
    { "Bob", 2 },
    { "Cindy", 3 }
};

C++11将初始化列表解释成一个initializer_list<T>类型的变量(T是列表中元素的类型)。
它相当于一个只读的容器,只有三个成员函数:size(),begin()和end()。
在上面这个例子中,我们用初始化列表为STL容器提供初值。
C++11为STL容器新增了一种构造函数,它可以接收一个initializer_list。

三. 应用

#include <initializer_list> // This header is required
#include <iostream>

using namespace std;

template <class Tp>
void print_ilist(const initializer_list<Tp> &ilist)
{
    for (auto it = ilist.begin(); it != ilist.end(); ++it)
        cout << *it << endl;
}

struct Foo
{
    int vals[10];
    int n = 0;

    Foo(const initializer_list<int> &ilist) {
        for (int v : ilist)
            vals[n++] = v;
    }
};

int main()
{
    initializer_list<int> empty_ilist;
    empty_ilist = { 1, 2, 3, 4 };
    cout << empty_ilist.size() << endl; // 4

    Foo foo{ 1, 2, 3 };
    Foo bar(empty_ilist);
    cout << "bar.n = " << bar.n << endl; // 4

    initializer_list<float> float_ilist{ 1.0, 1.2, 1.5, 2.0 };
    print_ilist(float_ilist);
    print_ilist({ "Reimu", "Marisa", "Sanae", "Reisen" });
    return 0;
}