C++类内初始化vector的一个小坑与分析解决

 
Category: C_C++

问题

先来看这样一份代码:

vector<vector<int>> v(10, vector<int>(10));

没有任何问题, 初始化一个10*10的全零二维数组, 但是, 如果在类内:

class P {
private:
    vector<vector<int>> v(10, vector<int>());
public:
    P() {}
    void print() {
        for (auto i : v) {
            for (auto j : i) cout << j << " ";
            cout << endl;
        }
    }
};

就会报错:

// clang++: error: expected parameter declarator
// g++: error: expected ',' or '...' before numeric constant
// error: expected identifier before numeric constant

那么这是为什么呢?

用一维数组试试:

class P {
private:
    vector<int> v(10);
public:
    P() {}
    void print() {
        for (auto i : v) cout << i << " ";
    }
};

还是一样的情况…

那么换初始化列表(C++11)呢?

vector<vector<int>> v{{1, 2}, {3, 4, 5}};

这样就可以了…

解决

declaring a vector - C++ Forum (cplusplus.com);

后来看cplusplus, 想起来了Effective STL item6, 当心C++编译器烦人的分析机制, 发现原来是括号的问题, 导致了二义性, 但是这只是作为类内数据成员来看的, 其他时候并不用担心, 解决方案是:

class P {
private:
    vector<int> v = vector<int>(10);

public:
    P() {}
    void print() {
        for (auto i : v) cout << i << " ";
    }
};

void t1() {
    //
    P p;
    p.print();
}
int main(int argc, char const *argv[]) {
    t1();
    return 0;
}

针对二维数组的初始化:

vector<vector<int>> v = vector<vector<int>>(10, vector<int>(10));

虽然冗余, 至少可行, 后来发现可以用一致性初始化.

#include <vector>
#include <iostream>
using namespace std;


class P {
private:
    vector<int> v;

public:
    P() : v(10) {}
    void print() {
        for (auto i : v) cout << i << " ";
    }
};

void t1() {
    //
    P p;
    p.print();
}
int main(int argc, char const *argv[]) {
    t1();
    return 0;
}

相当完美. 二维类似:

#include <vector>
#include <iostream>
using namespace std;


class P {
private:
    vector<vector<int>> v;

public:
    P() : v(10, vector<int>(10)) {}
    void print() {
        for (auto i : v) {
            for (auto j : i) cout << j << " ";
            cout << endl;
        }
    }
};

void t1() {
    //
    P p;
    p.print();
}
int main(int argc, char const *argv[]) {
    t1();
    return 0;
}