C++11的初始化语法

王子亭 发布于 2012/12/23 00:51
阅读 6K+
收藏 6

首先我要强调,C++中struct和class唯一的区别是,前者的成员默认公有,后者成员默认私有.

在C++03中,结构体/类的初始化方式只有来自C语言的一种写法:


struct A
{
    int x;
    int y;
};

A a{123,456};  //a.x=123; a.y=456

在C++中,有一个POD(Plain old data structure)的概念,指C风格的,纯数据(没有成员函数)构成的结构体/类,大概是这个意思,具体如何界定什么事POD我不清楚.

上面的写法,只建议在POD结构体/类上使用,不建议在含有成员函数的结构体/类上使用.

-------------------------------

在C++11中,统一了初始化的写法,任何数据类型,都可以用花括号来初始化,例如(以下所有写法都等价):


//下面三行来自C++03:
int a1=1;
int a2=int(1);
int a3(1);
//下面是C++11新增的:
int a4={1};
int a5{1};


以上所有写法都适用于结构体/类,将会都和【int a3(1);】等价,调用对应的构造函数,如果构造函数有两个参数,则这么写:


A a2=A(1,2);
A a3(1,2);
A a4={1,2};
A a5{1,2};


-------------------------------

可以发现,C++11新增的花括号初始化方法是和C风格的结构体初始化有冲突的:


struct A
{
   int x;
   int y;
   A(int x,int y){}
};

A a{123,456};


这句既可以认为是C风格的结构体初始化,也可以认为是C++11的花括号初始化,那么到底如何呢,本人在GCC4.6的测试(我在标准中没找到规定):

  • 优先查找构造函数,如果有对应的构造函数,使用构造函数.
  • 如果没有构造函数,按照C风格,对x和y逐个赋值.

所以前面提到不建议在非POD结构体/类(含有成员函数的结构体/类)中使用C风格的结构体初始化.

-------------------------------

C++11还新增了一个特征:


A func()
{
    //C++03风格:
    return A(123,456);
    //C++11风格:
    return {123,456};
}


C++11风格的return可以省略类型名,这仅适用于return,因为在函数头中已经包含了返回值类型.

-------------------------------

C++11还新增了std::initializer_list,这是一个语言层面的模版类,可以让你自由地使用花括号传递数据:

如果一个类有一个接受std::initializer_list类型参数的构造函数


struct B
{
  B(std::initializer_list<int> list){}
};

B b = {1, 4, 5, 6};


那么你就可以这样来初始化,花括号里面的参数会被打包成std::initializer_list类型,并调用对应的构造函数,C++11中的标准库容器,如vector都支持这种语法.
如果类中含有std::initializer_list构造函数,那么使用花括号语法会始终调用该函数(而不是像上面【A a{123,456};】那样,调用【A(int x,int y){}】,也不是C风格的结构体初始化.).

std::initializer_list还可以作为函数参数:


void func(std::initializer_list<int> list)
{

}

func({1, 4, 5, 6});


以上代码在windows7+gcc4.6测试通过,代码均省略了main函数.


加载中
1
diguo2046
diguo2046
更多新功能新语法, 点击查看 http://zh.wikipedia.org/wiki/C%2B%2B11
0
Timor君
Timor君
新的东西一时难以接受啊,所以不想接触11了
0
Jooooooker
Jooooooker
窃以为最靠谱的C++11里面的新东西 就是那个auto了
ddatsh
ddatsh
auto +1
Jooooooker
Jooooooker
回复 @洪文军 : 哦对 还有foreach~~~
氵共
遍历方便多了
0
梦游的睡鼠

这个东西唯一的用处就是当你继承了或者包含了一个没有构造函数的struct时,又想在构造函数里简单地对它初始化的时候使用:

struct Base
{
    int A;
    int B;
};

class Extend : public Base
{
public:
    Extend(int A, int B) :
        Base({A, B})
    {

    }
};



如果能定义构造函数尽量用构造函数来初始化,不要钻这些空子,这只会让代码更难懂。像"return {x, y};"这种东西见一次打一次。

返回顶部
顶部