C++开发初级


1304 浏览 5 years, 3 months

3.1.7 初始化列表构造函数(仅限C++11)

版权声明: 转载请注明出处 http://www.codingsoho.com/
初始化列表构造函数(仅限C++11)

初始化列表构造函数(Initializer-List Constructors)是将std::initializer_list<T>作为第一个参数的构造函数,并且没有任何其他参数(或者其他参数具有默认值)。在使用std::initializer_list<T>模板之前,必须包含<initializer_list>头文件。下面的类演示了这种用法。

class PointSequence
{
public:
    PointSequence(initializer_list<double> args)
    {
        if (args.size() % 2 != 0)
            throw invalid_argument("initializer_list should contain even number of elements.");
        for (auto iter = args.begin(); iter != args.end(); ++iter)
            mVecPoints.push_back(*iter);
    }
    void dumpPoints() const
    {
        for (auto citer = mVecPoints.cbegin(); citer != mVecPoints.cend(); citer += 2) {
            cout << "(" << *citer << ", " << *(citer+1) << ")" << endl;
        }
    }
protected:
    vector<double> mVecPoints;
};

代码取自 InitializerListCtor\InitializerListCtor.cpp

在前面的示例中,初始化列表构造函数内部可以使用迭代器访问初始化列表的元素。迭代器将在后面讨论。可用sizes方法获取初始化列表中元素的数目。

可按照以下方式创建PointSequence对象:

    PointSequence p1 = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
    p1.dumpPoints();
    try {
        PointSequence p2 = {1.0, 2.0, 3.0};
    } catch (const invalid_argument& e) {
        cout << e.what() << endl;
    }

代码取自 InitializerListCtor\InitializerListCtor.cpp

创建p2时会抛出一个异常,因为初始化列表中元素数目为奇数。前面的等号是可选的,可以忽略,例如:

PointSequence p1 = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};

C++ 11 STL完全支持初始化列表构造函数。例如,可使用初始化列表初始化std::vector容器。

std::vector<std::string> myVec = {"String 1", "String 2", "String 3"};

如果您使用的编译器不支持C++11标准,可以调用一些push_back()来初始化向量:

std::vector<std::string> myVec;
myVec.push_back("String 1");
myVec.push_back("String 2");
myVec.push_back("String 3");

初始化列表构造函数对于C++11的统一初始化(uniform initialization)功能非常重要,这一功能将在后面讲述。

初始化列表并不限于构造函数,还可以用于普通函数,后面将讲述这一内容。

上面我们用到的C++的新特性auto,简单介绍一下

auto

C++11引入auto关键词,推测类型

auto i=42; //推测类型为int
double f();
auto d=f(); //根据f的返回值推测d为double
vector<string> v;
auto it=v.begin(); //推测类型为vector<string>::iterator

不能用auto定义未分配变量,下面是错误的

auto i;

在可以推测数据类型的环境下,使用auto代替数据 类型,由编译器确定具体的类型。

基于范围的for循环

C++11为基于迭代器区间的容器或数组等构建提供新的for循环

for( elem : coll ) {  }

凡是支持foreach的操作,都可以使用for替代

int a[]={1,3,2,5,6};
for( int i : a){ 
    cout<<i<<endl; 
}

上面for循环遍历数组中元素,但不能修改元素。

for(auto& elem : a){ 
    elem*=2; 
}

通过引用,可以修改数组元素。

for的另一个示例

vector<int v;
v.push_back(3);
// …
int sum=0;
for(const auto& elem : v)
    sum+=elem;

for的等价形式

for( elem : coll ) {  }
// Equal to below 
auto it=coll.begin();
for(; it!=coll.end(); ++it)
{
    const auto& elem = *it;
    
}