首页 > 程序人生 > 漫话C++0x(三)

漫话C++0x(三)

本文是《漫话C++0x》系列的第三篇,接前面的内容,继续为大家介绍一些C++0x中增加的比较好玩的特性。我们知道变量的初始化在C++中是一个比较重要的话题,好的编程习惯建议大家在声明变量的时候最好初始化,这样可以避免一些不必要的问题。另外,在C++98中,变量的初始化(initialization)和赋值(assignment)是两个比较重要的概念,这里大家可以回顾一下,比如常量只能初始化,不能赋值。

今天要讲的主要内容就是C++0x中新增加的统一初始化的语法,通过与C++98中的对比,我们来加深对C++0x的理解。下面我们来看一些C++98中初始化的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/// 各种形式的初始化
const int x(5);           ///< 直接初始化
const int y = 5;          ///< copy构造初始化
int arr[] = {1, 2, 3};    ///< 大括号初始化
struct Point{int x, y;};
const Point p = {1, 2};   ///< 大括号初始化
class PointX
{
public:
    PointX(int x, int y);
private:
    int x, y;
};
const PointX px(1, 2);    ///< 构造函数初始化
std::vector< int> vec(arr, arr+3); ///< 从别的容器初始化

从上面的例子,我们可以看到,C++98支持各种各样的初始化方式,另外,还有一些在C++98中不能直接初始化的情况,如下所示:

1
2
3
4
5
6
7
8
9
/// 不能初始化的情况
class Foo
{
public:
    Foo() : data(???) {} ///< 不能在这里初始化数组
private:
    int data[3];
};
int * data = new int[3]; ///< 不能在这里初始化堆上内存

上面的例子,相信有C++基础的朋友一看就会懂,我们看到,在C++98中初始化是这样的复杂,有多种的形式,还有不能初始化的,实在是太麻烦了。正是基于这样的情况,C++0x提出统一了初始化的语法,并且支持所有类型的初始化,彻底把C++程序员从这种复杂的逻辑中解放出来。C++0x中,初始化都可以通过大括号初始化来完成,可以用在各种地方,下面先看例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/// 与上面c++98中能初始化的例子相对应
int x {1};
int y {2};
int arr[] {x, y, 3};
struct Point {int x, y;};
Point p {1, 2};
class PointX
{
public:
    PointX(int x, int y);
private:
    int x, y;
};
PointX px {1, 2};
std::vector< int> vec {1, 2, 3};
 
/// 与上面C++98中不能初始化的例子相对应
class Foo
{
public:
    Foo() : data {1,2,3} {}
private:
    int data[3];
};
int * data = new int[3] {1, 2, 3};

从上面的例子中,我们可以看到,C++0x中,所有的初始化都可以用{}来完成了,达到了真正意义上的统一,语法也十分简洁。另外,原来在C++98不能直接初始化的情况,C++0x也顺带解决了。不急,还有更炫的地方,先看下面的例子:

1
2
3
void Func(const std::vector< int>& v);
Func({1, 2, 3, 4, 5});
Point MakePoint() { return { 0, 0 }; }

看到这里,不知道大家有没一种觉得很炫的感觉,我个人是觉得,C++0x已经把这个统一初始化做到了极致,既统一了形式,又支持了很多方便的用法,简洁、实用。
上面举了不少例子,相信大家对C++0x中统一初始化的语法已经有了比较深刻的认识,这里还有一些需要补充的点,帮助大家更好的理解C++0x中的初始化:

1. 在C++中,有集合类型(Aggregates)和非集合类型(Non-Aggregates)之分,集合类型包括数组和用户没有提供构造函数、没有protected/private的非静态成员、没有基类、没有虚函数的class类型。其它都属于非集合类型。对于这两种类型,C++0x采用了不同的初始化的逻辑(虽然形式上一样):
(1)对于集合类型,采用从头到尾,每个元素逐一初始化的方式进行初始化
(2)对于非集合类型,调用该类型的构造函数进行初始化

2. 在C++0x的的统一初始化逻辑中,参数的个数可以少于成员,但不能多于,如果少于的话,没初始化的成员通过缺省的方式初始化

1
2
3
struct Point {int x, y;};
Point p1 {1};       ///< ok
Point p2 {1, 2, 3}; ///< error!

3. C++0x中增加了一种新的类型std::initializer_list, {}初始化列表可以转为std::initializer_list类型,这个类型也可以直接由{}来初始化

4. C++0x的{}初始化逻辑还支持=号,不过因为=号不是在所有的情况都适用,所以这里不建议在{}初始化的时候使用=,培养直接使用大括号初始化的习惯即可。

1
2
3
const int x = {1};
struct Point {int x, y;};
Point p = {1, 2};

以上即是本文的主要内容,下节将对C++0x中的lambda表达式进行分享,lambda表达式是一个有着质的飞跃的特性,相信了解完它之后,大家都会爱上它的,欲知详情,且听下回分解!

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.
您必须在 登录 后才能发布评论.