• C++11中的std::initializer_list<T>的使用


    initializer_list是一种标准库类型,用于表示某种特定类型的值的数组。和vector一样,initializer_list也是一种模板类型,定义initializer_list对象时,必须说明列表中所含元素的类型。和vector不一样的是,initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。

    initializer_list可以作用于可变数量的实参:有时我们无法提前预知应该向函数传递几个实参。为了编写能处理不同数量实参的函数,C++11新标准提供了两种主要的方法:如果所有的实参类型相同,可以传递一个名为initializer_list的标准库类型;如果实参的类型不同,我们可以编写一种特殊的函数,也就是所谓的可变参数模板。

    作用于initializer_list对象的begin和end操作类似于vector对应的成员。begin()成员提供一个指向列表首元素的指针,end()成员提供一个指向列表尾元素的指针。

    含有initializer_list形参的函数也可以同时拥有其他形参。

    类模板initializer_list用于访问初始化列表(initialization list),列表元素的数据类型为const T.编译器从花括号(brace)封闭的、元素由逗号分隔开的初始化列表自动构造initializer_list模板类, 例如:

    auto il = {10,20, 30}; // the type of il is an initializer_list<int>

    类模板initializer_list引用(refer to)但不包含这个这个列表的元素。复制这个initializer_list对象将引用到同一个基础列表而不是引用到基础列表的新的拷贝。std::initializer_list并不是一个容器,不要用它传递期望长期存储的值。构造函数的形参如果为一个initializer_list模板类,则这种特殊的构造函数称为初始化器列表构造函数(initializer_list constructor),例如:

    struct myclass {
      myclass (int,int);
      myclass (initializer_list<int>);
      /* definitions ... */
    };
    myclass foo {10,20};  // calls initializer_list constructor
    myclass bar (10,20);  // calls first constructor 

    仅可以从braced-init-list推导出initializer_list<T>。这一过程中,编译器自动查询哪些构造函数可以用initializer_list<T>作为参数,并据此确定initializer_list的模板参数T的类型,从而对braced-init-list做类型转换。

    C++11标准明确规定不能由模板参数推导出对应实参std::initializer_list的类型。

    C++还有一种特殊的形参类型(即省略符),可以用它传递可变数量的实参。

    省略符形参是为了便于C++程序访问某些特殊的C代码而设置的,这些代码使用了名为varargs的C标准库功能。通常,省略符形参不应用于其他目的。省略符形参只能出现在形参列表的最后一个位置。

    下边是我的一个测试例子:

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <initializer_list>
    
    struct myclass {
        std::string s;
        myclass(std::initializer_list<int> args) {
            std::stringstream ss;
            for (auto it = args.begin(); it != args.end(); ++it)
            {
                ss << ' ' << *it;
                //s = ss.str();
            }
            s = ss.str();
            std::cout << "myclass--counstruction" << std::endl;
        }
    
        void display() {
            std::cout << s << std::endl;
        }
    };
    
    int main(int argc, char* argv[])
    {
        myclass a = { 1,2,3,4,5 };
        a.s[1] = '5';
        a.display();
        system("pause");
        return 0;
    }

    这个例子我不仅尝试了使用初始化器列表构造函数,同时我还测试了通过其构造的数据成员(着里是s)是可以修改的【当然如果没有修改的必要就当这个测试是废材吧~】。

    对了,还有一点:我们可以用initializer_list的对象去初始化一个智能指针对象,就像这样:

    template <class T>
    Blob<T>::Blob(std::initializer_list<T> il):
    data(std::make_shared<std::vector<T>>(il)){}
    温润如玉,坚毅如铁。
  • 相关阅读:
    一个判断浏览器类型的JS
    asp中输出xml “文本内容中发现无效字符”问题的解决(转)
    Excel VBA工程密码之最简单破解法
    爆破AspriseOCR 4.0
    vi编辑器的使用(转载)
    数据挖掘(转载)
    简单工厂模式(SimpleFactory)
    工厂方法模式(Factory Method)
    让gridview默认处于编辑模式并取得编辑后的值
    GDB调试精粹及使用实例(转载)
  • 原文地址:https://www.cnblogs.com/heisen/p/9342182.html
Copyright © 2020-2023  润新知