无用知识研究:std::initializer_list的秘密

news/2025/2/6 13:07:38 标签: c++, 算法

先说结论,用std::initializer_list初始化vector,内部逻辑是先生成了一个临时数组,进行了拷贝构造,然后用这个数组的起终指针初始化initializer_list。然后再用initializer_list对vector进行初始化,这个动作又触发了拷贝构造。

所以说,用initializer_list初始化,还是有优化空间的。

感觉吧,如果你真想用vector保存对象,减少一半的拷贝动作的方法:最好用vector的emplace_back把数据给move进去,或者原地初始化。

或者,就用vector保存指针

std::vector<std::string> vec1{ "ant", "bat", "cat" };

 运行到initializer_list的构造函数:

D:\DevTools\VS2017\VC\Tools\MSVC\14.16.27023\include\initializer_list

template<class _Elem>
	class initializer_list
	{	// list of pointers to elements
public:
	typedef _Elem value_type;
	typedef const _Elem& reference;
	typedef const _Elem& const_reference;
	typedef size_t size_type;

	typedef const _Elem* iterator;
	typedef const _Elem* const_iterator;

	constexpr initializer_list() noexcept
		: _First(nullptr), _Last(nullptr)
		{	// empty list
		}

	constexpr initializer_list(const _Elem *_First_arg,
		const _Elem *_Last_arg) noexcept
		: _First(_First_arg), _Last(_Last_arg)
		{	// construct with pointers
		}  //。。。。。。。。。。。。。。。。运行到这里。。。。。。。。。。。。。。

..........

};

这个std::initializer_list是怎么个事呢,它就是一个wrapper,一个viewer。注意它的构造函数,接收的是起始指针和末尾的指针。所以std::initializer_list就是保存了起终指针。所以std::initializer_list对象的拷贝,也是属于“浅拷贝”,保存的都是指针,不影响它们指向的数据。

下面的描述,说明了:

https://cplusplus.com/reference/initializer_list/initializer_list/

initializer_list objects are automatically constructed as if an array of elements of type T was allocated, with each of the elements in the list being copy-initialized to its corresponding element in the array, using any necessary non-narrowing implicit conversions.

The initializer_list object refers to the elements of this array without containing them: copying an initializer_list object produces another object referring to the same underlying elements, not to new copies of them (reference semantics).

The lifetime of this temporary array is the same as the initializer_list object.

通过这个了例子,说明了初始化initializer_list所用的起终指针,是来自于一个
“数组”,这个数组提前被拷贝构造函数初始化过了。相当于先进行了三次拷贝动作。

class MyDate
{
public:
    MyDate()//构造函数
    {
        std::cout << "构造函数 this地址 " << this << std::endl;
    }

    ~MyDate()//析构函数
    {
        std::cout << "析构函数" << std::endl;
    }
    MyDate(std::initializer_list<MyDate>& d)//initializer_list拷贝构造函数
    {
        std::cout << "initializer_list拷贝构造函数" << std::endl;
    }
    MyDate(const MyDate& d)//拷贝构造函数
    {
        std::cout << "/拷贝构造函数 scr地址 " << &d << std::endl;
        std::cout << "拷贝构造函数 this地址 " << this << std::endl;
    }

    MyDate& operator=(const MyDate& d)//赋值运算符重载
    {
        std::cout << "赋值运算符重载" << std::endl;
        return *this;
    }

    MyDate* operator&()//取地址运算符重载(&)
    {
        std::cout << "取地址运算符重载(&)" << std::endl;
        return this;
    }

    const MyDate* operator&() const//const修饰的取地址运算符重载(const &)
    {
        //std::cout << "const修饰的取地址运算符重载(const &)" << std::endl;
        return this;
    }

    int val;
};

int main()
{
构造函数 this地址 000000000014F1C4
        MyDate d0; 

        std::cout << "d0 already initialized" << std::endl;
        std::cout <<  std::endl;

/拷贝构造函数 scr地址 000000000014F1C4  “看地址,说明用d0进行的初始化”
拷贝构造函数 this地址 000000000014F1E4
        MyDate d1{ d0};

        std::cout << "d1 already initialized" << std::endl;
        std::cout << std::endl;

打印信息
//拷贝构造函数 scr000000000014F1C4 “看地址,说明用d0进行的初始化”
拷贝构造函数 this000000000014FDA8
/拷贝构造函数 scr000000000014F1C4 “看地址,说明用d0进行的初始化”
拷贝构造函数 this000000000014FDAC
/拷贝构造函数 scr000000000014F1C4 “看地址,说明用d0进行的初始化”
拷贝构造函数 this000000000014FDB0

解释:
初始化了一个长度为3的“临时”数组,用d0进行了三次构造拷贝动作,数组中每个对象的地址分别为
000000000014FDA8
000000000014FDAC
000000000014FDB0

紧接着打印:
/拷贝构造函数 scr地址 000000000014FDA8
拷贝构造函数 this地址 00000000005E3660
/拷贝构造函数 scr地址 000000000014FDAC
拷贝构造函数 this地址 00000000005E3664
/拷贝构造函数 scr地址 000000000014FDB0
拷贝构造函数 this地址 00000000005E3668

解释:
这些打印信息,是把临时数组里的对象拷贝进了vector里:
vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc())
		: _Mybase(_Al)
		{	// construct from initializer_list, optional allocator
		_Range_construct_or_tidy(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{});
		}

        std::vector < MyDate> d2{ d0,d0,d0 };


//std::vector < MyDate> d2{ d0,d0,d0 };这段代码相当于:
//std::vector<MyDate> dt;
//dt.reserve(3);
//dt.emplace_back(d0);
//dt.emplace_back(d0);
//dt.emplace_back(d0);
//std::initializer_list lst(dt.begin(), dt.end());
//std::vector < MyDate> d2(lst); //对vector用initializer_list进行初始化

        return 1;
}

 


http://www.niftyadmin.cn/n/5843015.html

相关文章

billd-live 一款开源、免费、技术先进的直播系统

一、简介 Billd-Live是一个基于Vue3、WebRTC、Node、SRS和FFmpeg等技术搭建的直播间系统&#xff0c;支持在线Web和安卓端查看。它实现了类似于bilibili的Web在线直播功能&#xff0c;允许用户发布直播并观看他人的直播内容。 二、功能 原生 webrtc 推拉流 srs webrtc 推流&…

通过docker安装部署deepseek以及python实现

前提条件 Docker 安装:确保你的系统已经安装并正确配置了 Docker。可以通过运行 docker --version 来验证 Docker 是否安装成功。 网络环境:保证设备有稳定的网络连接,以便拉取 Docker 镜像和模型文件。 步骤一:拉取 Ollama Docker 镜像 Ollama 可以帮助我们更方便地管理…

20250205确认荣品RK3566开发板在Android13下可以使用命令行reboot -p关机

20250205确认荣品RK3566开发板在Android13下可以使用命令行reboot -p关机 2025/2/5 16:10 缘起&#xff1a;荣品RK3566开发板在Android13下&#xff0c;希望通过Native C语言程序来控制RK3566的关机。 通过ADB&#xff0c;很容易通过reboot -p命令关机。 最开始以为需要su/root…

高级java每日一道面试题-2025年01月28日-框架篇[SpringBoot篇]-如何使用Spring Boot实现异常处理?

如果有遗漏,评论区告诉我进行补充 面试官: 如何使用Spring Boot实现异常处理? 我回答: 在 Java 高级面试中讨论如何使用 Spring Boot 实现异常处理时&#xff0c;我们可以从多个角度进行详细阐述。这包括全局异常处理、特定异常处理、使用 ResponseStatus 注解、自定义异常…

GitHub Copilot 越狱漏洞

研究人员发现了两种操控 GitHub 的人工智能&#xff08;AI&#xff09;编码助手 Copilot 的新方法&#xff0c;这使得人们能够绕过安全限制和订阅费用、训练恶意模型等。 第一种技巧是将聊天交互嵌入 Copilot 代码中&#xff0c;利用 AI 的问答能力&#xff0c;使其产生恶意输…

PyQt6/PySide6 的 QTreeView 类

QTreeView 是 PyQt6 或 PySide6 库中用于显示分层数据的控件。它适用于展示树形结构的数据&#xff0c;如文件系统、组织结构等。QTreeView 也是基于模型-视图架构的&#xff0c;通常与 QAbstractItemModel 的子类&#xff08;如 QStandardItemModel 或自定义模型&#xff09;一…

最新EFK(Elasticsearch+FileBeat+Kibana)日志收集

文章目录 1.EFK介绍2.操作前提3.FileBeat8.15下载&安装4.编写FileBeat配置文件5.启动FileBeat6.模拟实时日志数据生成7.查看索引(数据流)是否创建成功8.创建数据视图&#xff1a;9.查看数据视图10.使用KQL对采集的日志内容进行过滤11.给日志数据配置保留天数(扩展知识) 1.E…

【力扣】48.旋转图像

AC截图 题目 思路 以矩阵 1 2 3 4 5 6 7 8 9 为例&#xff0c;想要翻转90度&#xff0c;可以先沿着对角线翻转一次 1 4 7 2 5 8 3 6 9 然后再逐行翻转&#xff0c;即可得到所求矩阵 7 4 1 8 5 2 9 6 3 代码 class Solution { public:void rotate(vector<vector…