1、基于范围的for循环
1)基于循环的迭代写法
int array[] = {1,2,3,4,5};
for(auto &x : array)
{
std::cout << x << std::endl;
}
2)容器遍历
std::vector<int> arr(5, 100); //arr数组包含5个100的元素
//原来遍历方式
for (std::vector<int>::iterator i = arr.begin(); i != arr.end(); ++i)
{
std::cout << *i << std::endl;
}
//C++11遍历方式
for (auto &i : arr)
{
std::cout << i << std::endl;
}
2、初始化列表
1)引出问题
在传统 C++ 中,不同的对象有着不同的初始化方法。不同方法都针对各自对象,不能通用。
例如普通数组、POD (plain old data,没有构造、析构和虚函数的类或结构体)类型都可以使用 {}进行初始化,也就是我们所说的初始化列表。而对于类对象的初始化,要么需要通过拷贝构造、要么就需要使用()进行。
比如:
int arr[3] = {1,2,3}; // 列表初始化
class Foo
{
public:
Foo(int) { }
private:
int value;
};
Foo foo(1);
2)解决方案
为了解决这个问题,C++11 首先把初始化列表的概念绑定到了类型上,并将其称之为 std::initializer_list,允许构造函数或其他函数像参数一样使用初始化列表,这就为类对象的初始化与普通数组和 POD 的初始化方法提供了统一的桥梁。
例如:
#include <initializer_list>
class Magic
{
public:
Magic(std::initializer_list<int> list) {}
};
Magic magic = {1,2,3,4,5};
std::vector<int> v = {1, 2, 3, 4};
这种构造函数被叫做初始化列表构造函数,具有这种构造函数的类型将在初始化时被特殊关照。初始化列表除了用在对象构造上,还能将其作为普通函数的形参。
例如:
void func(std::initializer_list<int> list)
{
return;
}
func({1,2,3});
另外,C++11提供了同一的语法来初始化任意的对象。
实例1:
struct A
{
int a;
float b;
};
struct B
{
B(int _a, float _b): a(_a), b(_b) {}
private:
int a;
float b;
};
A a {1, 1.1}; // 统一的初始化语法
B b {2, 2.2};
实例2:通过初始化列表初始化对象
class Foo
{
public:
Foo(int) {}
private:
Foo(const Foo &);
};
int main(void)
{
Foo a1(123);
Foo a2 = 123; //error: 'Foo::Foo(const Foo &)' is private
Foo a3 = { 123 };
Foo a4 { 123 };
int a5 = { 3 };
int a6 { 3 };
return 0;
}
说明:
- a3、a4 使用了新的初始化方式来初始化对象,效果如同 a1 的直接初始化。
- a5、a6 则是基本数据类型的列表初始化方式。可以看到,它们的形式都是统一的。
- 注意的是,a3 虽然使用了等于号,但它仍然是列表初始化,因此,私有的拷贝构造并不会影响到它。
- a4 和 a6 的写法,是 C++98/03 所不具备的。在 C++11 中,可以直接在变量名后面跟上初始化列表,来进行对象的初始化。
实例3:普通数组和POD类型的初始化
int i_arr[3] { 1, 2, 3 }; //普通数组
struct A
{
int x;
struct B
{
int i;
int j;
} b;
} a { 1, { 2, 3 } }; //POD类型
在初始化时,{}前面的等于号是否书写对初始化行为没有影响。
实例4:new操作符可以用圆括号进行初始化的地方,也可以使用初始化列表
int* a = new int { 123 };
double b = double { 12.12 };
int* arr = new int[3] { 1, 2, 3 };
指针 a 指向了一个 new 操作符返回的内存,通过初始化列表方式在内存初始化时指定了值为 123。
实例5:函数返回值
struct Foo
{
Foo(int, double) {}
};
Foo func(void)
{
return { 123, 321.0 };
}
这里的 return 语句就如同返回了一个 Foo(123, 321.0)。
本文详细介绍了C++11引入的基于范围的for循环和初始化列表这两项新特性。基于范围的for循环简化了遍历数组和容器的操作,减少了代码量并提高了可读性。初始化列表则统一了对象初始化的方式,包括对类对象和普通数组的初始化。文中通过多个实例展示了这两种新特性的使用方法,包括如何在构造函数中接受初始化列表,以及在new操作、函数返回值等场景的应用。
3028

被折叠的 条评论
为什么被折叠?



