Skip to content

initializer_list

初值列表可以用来初始化一个类,使用{}包裹元素即可, 为所有类和内置类型提供统一的初始化方法。

initializer_list

使用

  • class()

使用()初始化,一定调用 ctor,不会调用 initializer_list

  • class{}

使用{}初始化,优先调用 initializer_list,如果不存在,则调用 ctor

c++
class Point{
public:
    Point(int a, int b){
        std::cout<< "Point(int a, int b)" << std::endl;
    }

    explicit Point(int a, int b, int c){
        std::cout<< "Point(int a, int b, int c)" << std::endl;
    }

    Point(std::initializer_list<int> l){
        std::cout<< "Point(initializer_list<int> l)" << std::endl;
    }
};

int main(int argc, char **argv) {
    Point{1};               // Point(initializer_list<int> l)
    Point(1, 2);            // Point(int a, int b)
    Point{1, 2};            // Point(initializer_list<int> l)
    Point p = {1, 2};       // Point(initializer_list<int> l)
    Point(1, 2, 3);         // Point(int a, int b, int c)
    Point{1, 2, 3};         // Point(initializer_list<int> l)
    Point q = {1, 2, 3};    // Point(initializer_list<int> l)
                            // Point(int a, int b, int c) is explicit!!!
}

要注意如果没有initializer_list,表达式Point q = {1, 2, 3}是有问题的, 因为Point(int a, int b, int c)不允许隐式调用。

c++
int i = int();  // 0
int j{};        // 0

内置标量也可以像类一样调用 ctor 初始化为 0。这不同于 java 额外封装了包装类:)。

TIP

没有明确写出类名 ctor 都被认为是 implicit

声明

c++
template<class _E>
class initializer_list
{
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;

private:
    iterator			_M_array;
    size_type			_M_len;

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(); }
}

应该注意 initializer_list 提供了 begin 和 end, 所以可以被用于 Range-Based for 循环

注意

initializer_list 的 ctor 不应该被声明为 explicit,应该允许进行隐式转换。 如果一个类的元素数目不定,通常是容器,使用 initializer_list 可以避免手动创建数组。 应该注意{}兼容(),所以使用{}更统一规范。