C++学习之初始化列表详解

 更新时间:2023年03月17日 14:07:44   作者:余识-  
这篇文章主要为大家详细介绍了C++中初始化列表的相关知识,文中的示例代码讲解详细,对我们学习C++有一定的帮助,需要的小伙伴可以了解一下

前言

本文主要介绍C++中地初始化列表

目前对初始化列表应该有两个方面的定义,一个是类的构造函数中使用的那个初始化表,另一个则是C++11出现的std::initializer_list

下面来分别探讨这两个的初始化列表的具体细节与使用方式

一、类的初始化表

首先是类中使用构造函数时的初始化表,其一般书写格式为:

class Test {
    int x;
    int y;
    Test(int _x) 
        :x(_x),y(0)
    {
    }
};

即:在构造函数小括号与大括号之间,添加一个符号 :,然后在其后依次写出要初始化的成员变量名称,其名称后面有一个(),该小括号中的值就是将要赋值给成员变量的值

但实际上面这个效果与下面这段代码的效果是完全一样的:

Test(int _x) 
{
    x = _x;
    y = 0;
}

但既然存在,那必然会有它的道理,不然也不可能会通过C++标准委员会的审核

所以下面我们再来看看这个例子:

class Test1 {
public:
	Test1(){
		cout << "Test1的默认构造函数" << endl;
	}
	Test1(const Test1& t) {
		cout << "Test1的拷贝构造函数" << endl;
	}
	const Test1& operator=(const Test1& t) {
		cout <<"Test1的赋值构造函数" << endl;
		return *this;
	}
};

class Test {
	Test1 m_t1;
public:
	Test(Test1 _t1)
		//:t1(_t1)
	{
		m_t1 = _t1;
	}
};
int main() {
	Test1 t1;
	Test t(t1);
}

代码略微有点长,但并不复杂:

1.声明一个Test1类,并写好它的三个构造函数,用于测试调用这三个函数的情况

2.声明一个Test类,用于测试当将一个Test1类作为成员变量,在给其赋值时发生的情况

3.在main函数中,首先实例化一个Test1类的对象t1,然后传递给Test类的构造函数中来实例化一个Test对象

首先是正常赋值情况下,其输出为:

Test1的默认构造函数
Test1的拷贝构造函数
Test1的默认构造函数
Test1的赋值构造函数

下面分析一下其输出的原因:

1.实例化t1对象时调用其默认构造函数输出

2.见t1传入构造函数时,会将t1拷贝给_t1,所以调用了拷贝构造函数

3.默认会实例化成员变量m_t1,所以会调用其构造函数

4.最后将_t1赋值给m_t1,调用了赋值构造函数

而如果将test的构造函数改一下,采用初始化表:

    Test(Test1 _t1)
        :t1(_t1)
    {
        //t1 = _t1;
    }

那么就会输出以下内容:

Test1的默认构造函数
Test1的拷贝构造函数
Test1的拷贝构造函数

前两行输出是和前面一样的,而第三行输出,则代替前面第三和第四行的输出

即:通过调用拷贝构造函数一次,来代替原本需要先默认构造,然后再赋值构造两大步骤

这就是有初始化列表这一特性的原因,通过减少构造,达到提高性能的作用

事实上,上面的代码还可以优化为:

    Test(Test1& _t1)
        :t1(_t1)
    {
    }

这样便去掉了第二行的输出,通过引用而减少了一次拷贝构造:

Test1的默认构造函数
Test1的拷贝构造函数

也就是说,对于类来说,一般我们使用初始化表会提高性能,而对于基本数据类型,其实没有什么提升

当初始化列表的好处也不仅仅于此,它的出现可以让我们初始化成员变量更加方便!

所以总的来说,能用初始化表就尽量用,基本没坏处。

二、initializer_list

紧接着便是C++11出现的initializer_list,这同样是个好东西

首先我们还是来看看其主要用途

比如以往如果我们想要初始化一个vector,那么就必须这样写:

    vector<int> v;
    v.push_back(1);
    v.push_back(1);
    v.push_back(1);
    v.push_back(1);
    v.push_back(1);
    v.push_back(1);
    v.push_back(1);

这难免有点难看,但有了initializer_list之后,我们就可以直接写为:

vector<int> v{1,1,1,1,1,1,1,1};

是不是方便多了!

注意我这里说的仅仅是方便,因为使用它并不会带来任何性能的提升,甚至会有些性能损失,它的出现就是为了方便我们程序员写代码的

其本质来说它就是一个模板,在标准库源文件中定义如下:

template <class _Elem>
class initializer_list

从这里可以看出来,它只有一个参数类型,所以你不能在一个初始化列表中放入不同的类型数据,比如:

vector<int> v{1 , 2.3 };

由于这里vector已经指定了类型为int,所以一旦使用小数就会报错

当然,其使用范围并不仅仅只是标准库,对于基本数据也是支持的:

    int a{ 10 }; 
    int b={ 10 };

上面两种写法都可以

如果我们想要给自己的类或函数添加一个初始化列表赋值怎么做呢?方法也很简单:

void test(initializer_list<int> ls) {
    for (auto i = ls.begin(); i != ls.end(); i++) {
        cout << *i << endl;
    }
}
int main() {
    test({1,2,3,4,5,5,6,7,8,9,10});
}

即:通过迭代器遍历即可

到此这篇关于C++学习之初始化列表详解的文章就介绍到这了,更多相关C++初始化列表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言宏定义的扩展定义讲解

    C语言宏定义的扩展定义讲解

    这篇文章主要介绍了C语言宏定义的扩展,宏定义是C语言提供的三种预处理功能的其中一种,这三种预处理包括:宏定义、文件包含、条件编译
    2022-12-12
  • 解析C++中的字符串处理函数和指针

    解析C++中的字符串处理函数和指针

    这篇文章主要介绍了解析C++中的字符串处理函数和指针,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C++结构体初始化的10种写法总结

    C++结构体初始化的10种写法总结

    这篇文章主要为大家详细介绍了10种C++中结构体初始化的写法,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-04-04
  • 一篇文章带你了解C语言的一些重要字符串与内存函数

    一篇文章带你了解C语言的一些重要字符串与内存函数

    这篇文章主要介绍了C语言字符函数、内存函数 功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • C语言创建链表错误之通过指针参数申请动态内存实例分析

    C语言创建链表错误之通过指针参数申请动态内存实例分析

    这篇文章主要介绍了C语言创建链表错误之通过指针参数申请动态内存,是链表创建过程中非常常见的经典错误。实例中做了较为详尽的分析,需要的朋友可以参考下
    2014-09-09
  • 详解C/C++如何发送与接收Kafka消息

    详解C/C++如何发送与接收Kafka消息

    系统之间通信方式很多如:系统之间调用(http/rpc等),异步间接调用如发送消息、公共存储等,算法工程为C/C++工程,本文将介绍如何在C/C++中如何发送与接收Kakfa消息(包含:Kafka的SASL认证方式),并提供了详细的源码和讲解,需要的朋友可以参考下
    2024-07-07
  • c语言实现两个单链表的交叉合并方式

    c语言实现两个单链表的交叉合并方式

    今天小编就为大家分享一篇c语言实现两个单链表的交叉合并方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • C++实现LeetCode(16.最近三数之和)

    C++实现LeetCode(16.最近三数之和)

    这篇文章主要介绍了C++实现LeetCode(16.最近三数之和),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言float内存布局示例详解

    C语言float内存布局示例详解

    这篇文章主要为大家介绍了C语言float内存布局示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • c++可变参数模板使用示例源码解析

    c++可变参数模板使用示例源码解析

    这篇文章主要为大家介绍了c++可变参数模板使用示例源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01

最新评论