C++98中的成員變量初始化
- 在聲明類的時候,對於靜態類型並且是常量類型,同時是枚舉或者是整型的變量可以使用=在聲明時初始化。
- 對於不符合上述要求的靜態變量可以在類外使用=進行初始化
- 對於非靜態類型可以說個初始化列表進行初始化
- 使用()對自定義類型進行初始化
- 使用{}對元素集合統一初始化
C++11中的成員變量初始化
在C++11中可以使用=或者{}就地初始化,類似於Java語言。
代碼示例
struct init{
int a = 1;
double b{1.2};
};
需要注意的是()不能與=和{}有相同的使用方式,代碼示例
#include<iostream>
using namspace std;
struct C
{
C(int i):c(i){};
int c;
};
struct init
{
int a = 1;
string b("test");//編譯通不過
C c(1); //編譯通不過
};
需要注意的是=和{}可以和初始化列表一起使用,而且初始化列表總是後作用於=和{}
C++11豐富{}初始化
使用{}豐富化向量初始化,代碼示例
#include<vector>
#include<map>
using namespace std;
int a[] = {1. 3. 5};
int b[] {2. 4. 6};
vector<int> c{1, 3, 5};
map<int, float> d = {{1, 1.0f}, {2, 2.0f}, {3, 3.0f}};
int f = {3 + 4};
int g(3 + 4); //可以與new結合用來申請堆內存
int h{3 + 4}; //可以與new結合用來申請堆內存
以上代碼在C++11中可以順利通過編譯,但是在C++98中確不可以通過編譯。可以發現上面的代碼的初始化列表僅在基本類型和stl元素可以使用,對於那些自定義類型,可以通過修改構造函數、重載運算符等操作。
示例代碼
#include<iostream>
#include<vector>
using namespace std;
class Mydata{
public:
Mydata& operator[] (initializer_list<int> l)
{
for(auto i = l.begin(); i != l.end(); i++)
idx.push_back(*i);
return *this;
}
Mydata& operator = (int v)
{
for(auto i = idx.begin(); i != idx.end(); i++)
{
d.resize((*i > d.size())? *i: d.size());
d[*i - 1] = v;
cout << v << endl;
}
idx.clear();
return *this;
}
void print()
{
for(auto i = d.begin(); i != d.end(); i++)
cout << *i << " " ;
}
private:
vector<int> idx;
vector<int> d;
};
int main()
{
Mydata d;
d[{2, 3, 5}] = 90;
d[{1, 4, 5, 8}] = 7;
d.print();
return 0;
}
{}初始化列表的優點
與其他的初始化方式相比,{}初始化是唯一一種可以防止類型收窄的初始化方式。所謂的類型收窄其實就是新類型不可以表示原來類型的情況,在類型轉換的過程中數據丟失。
示例代碼
#include<iostream>
using namespace std;
int main()
{
const int x = 1024;
const int y = 10;
char a = x; //收窄,編譯可以通過
char *b = new char(1024);//收窄,編譯可以通過
char c = {x}; //收窄,編譯可以通過
char d = {y}; //編譯可以通過
unsigned char e {-1}; //收窄,編譯無法通過
float f{ 7 }; //編譯可以通過
int g { 2.0f }; //收窄,編譯無法通
float *h = new float{1e48}; //收窄,編譯無法通
float i = 1.2l; //可以通過編譯
return 0;
}