rdbuf的生命周期和使用

时间:2014-06-13 14:19:56

标签: c++ c++11 ifstream

以下代码有效,并且它看起来不像提供一些不良或不需要的行为,例如未定义的行为或不正确的结果。代码按预期工作,我的观点是:为什么?

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范围内?

1 个答案:

答案 0 :(得分:3)

临时对象(通过绑定到引用而不是生命周期扩展)在封闭的完整表达式(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>对象 - 在构造函数调用完成之后才会被销毁。