109.C++类内初始化
C++11规定,可以为数据成员提供一个类内初始值。创建对象时,类内初始值用于初始化数据成员。像下面这样,cursor和height的类内初始值均为0。
class Screen
{
private:
int cursor = 0;
int height = 0;
};
1.不能用圆括号给类内初始值的原因
C++ primer(第5版)中写道:类内初始值的提供必需以=或者花括号{}的形式。不能用园括号()。
关于这一点,可以参考网上的一个说法,如下:
由于无法避免下面的这种情况,这相当于对于int z(int);函数的声明,所以C++把用圆括号进行类内初始值定义为非法。
class Widget
{
private:
typedef int x;
int z(x);
};
2.=和花括号{}初始化的区别
2.1内置类型和类类型
对于这两者而言,=和{}初始化的区别不大,测试如下。
#include <iostream> // std::cout
#include <string>
#include <vector>
using namespace std;
int main()
{
std::cout << "*****内置类型*****" << std::endl;
int ival = 1;
int ival2{ 1 };
int ival3 = { 1 };//实际上先构造一个{ 1 }匿名对象然后拷贝给ival3
std::cout << "ival = " << ival << std::endl;
std::cout << "ival2 = " << ival2 << std::endl;
std::cout << "ival3 = " << ival3 << std::endl;
std::cout << "*****类*****" << std::endl;
string str = "aa";
string str2{ "aa" };
string str3 = { "aa" };//实际上先构造一个{ "aa" }匿名对象然后拷贝给str3
std::cout << "str = " << str << std::endl;
std::cout << "str2 = " << str2 << std::endl;
std::cout << "str3 = " << str3 << std::endl;
system("pause");
return 0;
}
输出:
*****内置类型*****
ival = 1
ival2 = 1
ival3 = 1
*****类*****
str = aa
str2 = aa
str3 = aa
请按任意键继续. .
2.2类模板
对于类模板而言,我们可以看看实际上初始化列表{}和=初始化的过程:
先看初始化列表{}:
std::vector<std::string> vs{ "ssss" ,"dddd"};
以看到,上面的初始化的最后一步是在vector中插入初始化列表中元素
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
_CONSTEXPR20 vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mybase(_Al)
{
insert(begin(), _First, _Last);
}
再看=的初始化过程:
因为它实际上是一个拷贝构造的过程,所以=的右边必须是一个同类型的值,如下所示。vs3可以看成是一个’std::vector类型的变量,那么只能用std::vector
类型的变量来初始化它,比如下面的vs_tmp。
std::vector<string> vs_tmp;
std::vector<string> vs3 = vs_tmp;
注意
,千万不能这样:std::vector<string> vs2 = "eee";
上述初始化最后调用的是vector的拷贝构造函数,如下:
总结:
- 初始化列表,列表中的元素就是模板的元素,如
vector<string> tmp_vec= {"ddd","www"}
- =初始化,只能用同类型,如只能用vector类型初始化vector类型
3.类内初始值的初始化列表{}方式
我在实际上调试时发现如下这样的一个问题:类内初始值的初始化列表{}方式编译器会报错。定义的类如下。
这让我很迷惑,因为在上面的测试中是可以的?后来才发现,因为我用的是VS2013,而它并不是完全支持C++11标准,所以对类内初始值用初始化列表的形式可能还不支持,换一个编译器后,不再报错。
class Wind_mgr
{
public:
void putsData()
{
str.push_back("aaa");
}
private:
std::vector<std::string> str{ "bbb" };//Error,无法从“const char [4]”转换为“const std::allocator<_Ty>”
};
最后附上vector的几种初始化形式:
初始化格式 | 说明 |
---|---|
vector v1 | 生成一个空vector |
vector v2(V1) | v2包含v1的所有元素副本 |
vector v2 = v1 | 等价于V2(V1) |
vector v3(n,val) | v3被初始化为n个val值,即v3有n个重复的元素 |
vector v4(n) | v4是一个有n个元素的vector,只是n个元素均为值初始化值 |
vector v5 | v5的大小就是初始化列表的大小,每个元素的值是初始化列表的值 |
vector v5 = | 等价于V5 |
vector v6 (first, last) | 将迭代器[first,last)区间的元素拷贝到v6 |