rbuf的生命周期和使用

The lifetime and the use of rdbuf

本文关键字:周期 生命 rbuf      更新时间:2023-10-16

下面的代码工作,它不像它提供一些坏的或不想要的行为,如未定义的行为或不正确的结果。代码按预期工作,我的问题是:为什么?

std::vector<char> v{std::istreambuf_iterator<char>{
                         std::ifstream{"yourFile.txt", std::ios::in}.rdbuf()},
                     std::istreambuf_iterator<char>{}}; 

这是对std::vector的构造函数的调用,它与迭代器一起工作,我的观点是关于rdbuf()调用的生命周期,并且rdbuf是一个指针而不是对象的事实,你不能只是复制rdbuf并假装它总是会到达你的文件的内容,也不能真正复制文件的整个内容而不使用迭代器。

我期待的是:

  • 有一个临时的ifstream对象
  • 从这个临时调用rdbuf
  • rdbuf现在在istreambuf_iterator的构造函数中,ifstream对象消失了
  • std::vector的构造函数现在应该使用指向一个不再存在的对象的指针的副本

我很惊讶这个东西能起作用,有人能说明为什么我错了,一步一步发生了什么?ifstream对象不应该是RAII兼容的,并且只出现在istreambuf_iterator的范围内

临时对象(当没有通过绑定到引用而延长生命期时)在封闭的完整表达式(c++ 11 12.2/3)的末尾被销毁:

当实现引入具有非平凡构造函数(12.1,12.8)的类的临时对象时,它应确保为该临时对象调用构造函数。类似地,对于带有非平凡析构函数的临时函数,也应该调用析构函数(12.4)。临时对象在(词法上)包含创建它们的点的完整表达式(1.9)求值的最后一步被销毁。即使该求值以抛出异常结束也是如此。销毁临时对象的值计算和副作用只与完整表达式相关联,而不与任何特定的子表达式相关联。

每1.9/10:

full-expression不是另一个表达式的子表达式。[注意:在某些上下文中,例如未求值的操作数,语法子表达式被认为是完整表达式(第5条)。- 结束注意] 如果定义了一种语言结构来产生对函数的隐式调用,则该语言结构的使用在本定义中被认为是表达式。对非临时对象的对象生命周期结束时生成的析构函数的调用是隐式的完整表达式。为满足出现该表达式的语言结构的要求而应用于表达式结果的转换也被认为是完整表达式的一部分。

你对v的声明"产生一个函数的隐式调用":双迭代器向量构造函数。因此,它被认为是一个完整表达式,因此临时ifstream对象(更不用说两个临时std::istreambuf_iterator<char>对象)在构造函数调用完成之前不会被销毁。