C++ primer plus 第16章string 类和标准模板库, 模板initializer list(C++11)

C++ primer plus 第16章string 类和标准模板库, 模板initializer list(C++11)

C++ primer plus 第16章string 类和标准模板库, 模板initializer list(C++11)


前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

16.7.2 模板initializer list(C++11)

模板 imnitializer list是C++11新增的。您可使用初始化列表语法将 STL容器初始化为一系列值:

std::vector<double>payments(45.9939.2319.9589.01};

这将创建一个包含4个元素的容器,并使用列表中的4个值来初始化这些元素。这之所以可行,是因为容器类现在包含将 initializer list作为参数的构造函数。例如,vector包含一个将initializer list作为参数的构造函数,因此上述声明与下面的代码等价:

std::vector<double>payments({45.99,39.2319.9589.01});

这里显式地将列表指定为构造函数参数。通常,考虑到 C++11新增的通用初始化语法,可使用表示法行而不是()来调用类构造函数:

shared ptr<double>pd(new double)://ok to use}instead of()

但如果类也有接受 initializer list 作为参数的构造函数,这将带来问题:// ??

std::vector<int>vi 10);

这将调用哪个构造函数呢?

//case A: 10 uninitialized elementsstd::vectorsint> vi(10);std::vector<int>vi((10));//case B:1 element set to 10

答案是,如果类有接受 initializer list作为参数的构造函数,则使用语法{)将调用该构造函数。因此在这个示例中,对应的是情形 B。
所有 imnitializer list 元素的类型都必须相同,但编译器将进行必要的转换:

std::vector<double>payments(45.9939.231989);// same as std::vector<double>payments(45.99,39.23,19.0,89.0};

在这里,由于 vector 的元素类型为double,因此列表的类型为initializer list,所以 19 和 89被转换为 double。
但不能进行隐式的窄化转换:

std::vector<int>values =(10,8,5.5);//narrowing,compile-time error

在这里,元素类型为int,不能隐式地将5.5转换为int。除非类要用于处理长度不同的列表,否则让它提供接受initializer list 作为参数的构造函数没有意义。例如,对于存储固定数目值的类,您不想提供接受 imitializer list 作为参数的构造函数。在下面的声明中,类包含三个数据成员,因此没有提供initializerlist作为参数的构造函数:

class Position
{
private:
int x;
int y;
int z;
public:
Position(intxx=0,intyy=0int zz=0)
:x(xx)y(yy)z(zz){}//no initializer list constructor
}

这样,使用语法行时将调用构造函数

Position(int,int,int):Position A={20,-3};//uses Position(20,-3,0)

16.7.3 使用initializer list

要在代码中使用 imitializer list对象,必须包含头文件 initializer list。这个模板类包含成员函数 begin()和end(),您可使用这些函数来访问列表元素。它还包含成员函数 size(),该函数返回元素数。程序清单 16.22 是一个简单的 initializer list 使用示例,它要求编译器支持 C++11 新增的initializer list。

程序清单16.22 ilist.cpp

// ilist.cpp  -- use initializer_list
#include <iostream>
#include <initializer_list>

double sum(std::initializer_list<double> il);
double average(const std::initializer_list<double> & ril);

int main()
{
    using std::cout;

    cout << "List 1: sum = " << sum({2,3,4})
         <<", ave = " << average({2,3,4}) << '\n';
    std::initializer_list<double> dl = {1.1, 2.2, 3.3, 4.4, 5.5};
    cout << "List 2: sum = " << sum(dl)
         <<", ave = " << average(dl) << '\n';
    dl = {16.0, 25.0, 36.0, 40.0, 64.0};
    cout << "List 3: sum = " << sum(dl)
         <<", ave = " << average(dl) << '\n';
    // std::cin.get();
    return 0;
}

double sum(std::initializer_list<double> il)
{
    double tot = 0;
    for (auto p = il.begin(); p !=il.end(); p++)
        tot += *p;
    return tot;
}

double average(const std::initializer_list<double> & ril)
{
    double tot = 0;
    int n = ril.size();
    double ave = 0.0;
    
    if (n > 0)
    {
        for (auto p = ril.begin(); p !=ril.end(); p++)
            tot += *p;
        ave = tot / n;
    }
    return ave;
}

程序说明
可按值传递 initializer list对象,也可按引用传递,如sumO和 average0)所示。这种对象本身很小,通

常是两个指针(一个指向开头,一个指向末尾的下一个元素),也可能是一个指针和一个表示元素数的整数,因此采用的传递方式不会带来重大的性能影响。STL按值传递它们。函数参数可以是 initializer list 字面量,如{2.3.4},也可以是 initializer list 变量,如 dl。initializer list的迭代器类型为 const,因此您不能修改 initializer list 中的值:

*dl.begin()= 2011.6;// not allowed

但正如程序清单16.22演示的,可以将一个 initializer list赋给另一个 initializer list:

dl={16.025.036.040.064.0};// allowed

然而,提供initializerlist类的初衷旨在让您能够将一系列值传递给构造函数或其他函数。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值