C++11(列表初始化,声明,范围for)

简介: C++11(列表初始化,声明,范围for)



一、列表初始化

1、一般的列表初始化

在C++98中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。

int main()
{
    int array1[] = { 1, 2, 3, 4, 5 };
    int array2[5] = { 0 };
    return 0;
}

而在C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

注:new 表达式初始化时一定不能写等号。

int main()
{
    int x1 = 1;
    int x2{ 2 };
    int array1[]{ 1, 2, 3, 4, 5 };
    int array2[5]{ 0 };
    int* pa = new int[4]{ 0 };
    return 0;
}

创建对象时也可以使用列表初始化方式调用构造函数初始化。如下图的d2和d3。

class Date
{
public:
    Date(int year, int month, int day)
        :_year(year)
        ,_month(month)
        ,_day(day)
    {
        cout << "Date(int year, int month, int day)" << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    Date d2{ 2022, 1, 2 };
    Date d3 = { 2022, 1, 3 };
    return 0;
}

2、容器的列表初始化

在 vector 和 list 这样的容器中,如果我们需要插入数据的话,我们就要通过 push_back 这样的函数去一个一个插入。但是,在c++11中,我们可以通过如下方式去插入数据:(等号也可以省略)。

vector<int> v1 = { 1,2,3,4 };
list<int> lt1 = { 1,2,3,4,5,6,7 };

这种插入的方式就非常方便,那么这种方式是怎么实现的呢?实现这种方式,就需要一个新的容器 了,这个容器叫 initializer_list。

它是C++11新增的容器,提供了 begin 和 end 函数,用于迭代器遍历;以及获取容器中的元素个数的 size 函数。

C++在语法层面会把 { } 认成 initializer_list,下面我们来看一看{ }的类型是什么:

auto x = { 1,2,3,4,5,6 };
cout << typeid(x).name() << endl;

从上图中我们发现该变量的类型就是 initializer_list 。

那么我们再来看一看vector的构造:

上面的(3)就是实现了 initializer_list ,这样就使得我们可以像上面那样对容器进行构造。

当用列表对容器进行初始化时,会被认为是initializer_list类型,此时不管有多少个值都能够被初始化vector,而以前我们必须使用 push_back 一个一个将元素插入。

所以现在有了C++11列表初始化的功能,我们也可以给我们自己之前模拟实现的vector和list容器加上这个功能,下面我就来给vector加上这个功能。

实现思路:遍历initializer_list 中的元素,然后push_back进要初始化的容器当中。

vector(initializer_list<T> il)
  :_start(nullptr)
  , _finish(nullptr)
  , _endofstorage(nullptr)
{
  typename initializer_list<T>::iterator it = il.begin();
  while (it != il.end())
  {
    push_back(*it);
    ++it;
  }
}

二、声明

1、 auto

在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto就没什么价值了。C++11中废弃auto原来的用法,将其用于实现自动类型推断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。

我们直接来使用一下它:

int main()
{
    int i = 10;
    auto p = i;
    cout << "i: " << typeid(i).name() << endl;
    cout << "p: " << typeid(p).name() << endl;
    map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
    //map<string, string>::iterator it = dict.begin();
    auto it = dict.begin();
    cout << "it: " << typeid(it).name() << endl;
    return 0;
}

2、decltype

关键字decltype将变量的类型声明为表达式指定的类型,即:根据表达式的实际类型推演出定义变量时所用的类型。

上面我们用到的 typeid 也能够推导出变量的类型,那么它们有什么区别呢?

typeid拿到的只是类型的字符串,不能用这个再去定义对象。下面的定义方式就不正确。

typeid(x).name() y = 20    //这样定义y不行

decltype 则可以推导出一个变量的类型,然后再去定义新的变量。如下图:

int x1 = 10;
decltype(x1) y1 = 20; //可以这样去定义y1

3、nullptr

由于C++中NULL被定义成字面量0,这样就可能回带来一些问题,因为0既能指针常量,又能表示整形常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针。 其定义如下:

#ifndef NULL
#ifdef __cplusplus
#define NULL  0
#else
#define NULL  ((void *)0)
#endif
#endif

三、 范围for

int main()
{
    string s("hello world");
    string::iterator it = s.begin();
    while (it != s.end())
    {
      cout << *it << " ";
      it++;
    }
    cout << endl;
  for (auto e : s)
  {
    cout << e << " ";
  }
  cout << endl;
}

上面两种遍历方式的结果完全相同。这是因为范围for本质上是迭代器,在代码编译的时候,编译器会自动将范围for替换为迭代器的形式去遍历。

目录
相关文章
|
2月前
|
编译器 C语言 C++
C++一分钟之-C++11新特性:初始化列表
【6月更文挑战第21天】C++11的初始化列表增强语言表现力,简化对象构造,特别是在处理容器和数组时。它允许直接初始化成员变量,提升代码清晰度和性能。使用时要注意无默认构造函数可能导致编译错误,成员初始化顺序应与声明顺序一致,且在重载构造函数时避免歧义。利用编译器警告能帮助避免陷阱。初始化列表是高效编程的关键,但需谨慎使用。
41 2
|
5天前
|
Dart API 开发工具
Dart ffi 使用问题之Dart API要在C++中使用,该如何初始化
Dart ffi 使用问题之Dart API要在C++中使用,该如何初始化
|
2月前
|
安全 C++ 开发者
C++一分钟之-RAII资源获取即初始化
【6月更文挑战第24天】RAII是C++中一种关键的资源管理技术,它利用对象生命周期自动获取和释放资源,减少内存泄漏。通过构造函数获取资源,析构函数释放资源,确保异常安全。优势包括自动性、异常安全和代码清晰。使用智能指针如`std::unique_ptr`和`std::shared_ptr`,以及标准库容器,可以避免手动管理。自定义RAII类适用于非内存资源。代码示例展示了智能指针和自定义RAII类如何工作。掌握RAII能提升程序的可靠性和可维护性。
32 6
|
1月前
|
编译器 C++
【C++】详解初始化列表,隐式类型转化,类静态成员,友元
【C++】详解初始化列表,隐式类型转化,类静态成员,友元
|
2月前
|
存储 编译器 C++
【C++】类和对象④(再谈构造函数:初始化列表,隐式类型转换,缺省值
C++中的隐式类型转换在变量赋值和函数调用中常见,如`double`转`int`。取引用时,须用`const`以防修改临时变量,如`const int& b = a;`。类可以有隐式单参构造,使`A aa2 = 1;`合法,但`explicit`关键字可阻止这种转换。C++11起,成员变量可设默认值,如`int _b1 = 1;`。博客探讨构造函数、初始化列表及编译器优化,关注更多C++特性。
|
2月前
|
容器
C++11 列表初始化(initializer_list),pair
C++11 列表初始化(initializer_list),pair
|
3月前
|
C++
C++ 类的初始化列表与构造函数初始化的技术性探讨
C++ 类的初始化列表与构造函数初始化的技术性探讨
27 0
|
3月前
|
Java 编译器 C语言
从C语言到C++⑦(第二章_类和对象_下篇)初始化列表+explicit+static成员+友元+内部类+匿名对象(下)
从C语言到C++⑦(第二章_类和对象_下篇)初始化列表+explicit+static成员+友元+内部类+匿名对象
21 0
|
7天前
|
存储 算法 搜索推荐
【C++】类的默认成员函数
【C++】类的默认成员函数
|
7天前
|
存储 安全 编译器
【C++】类和对象(下)
【C++】类和对象(下)
【C++】类和对象(下)