持有std :: ostream rvalue成员时的行为异常

问题描述

#include <iostream>
#include <fstream>

class A {
private:
  std::ostream&& out;  
public:
    A(std::ostream&& o) : out(std::move(o)) {
        out.write("test",4);
    }
    
    void writeTest2() {
        out.write("test2",5);
        out.flush();  // still does nothing.
    }
};

int main() {
    A a{std::ofstream{"testic"}};
    a.writeTest2();
}

运行上述代码时,将按预期方式创建名为testic文件。但是,创建的文件包含test但不包含testtest2,这显然是意外的。究竟是什么导致了此行为?

std::ostream用作左值引用时,它可以按预期运行。

其他信息

  • 编译器尝试: clanggcc
  • 在平台上: Linux(4.19.0-11-amd64)

解决方法

您创建的临时std::ofstream{"testic"}仅在构造函数调用期间存在。之后,它将销毁并关闭文件,这意味着您将获得一个引用垃圾的引用。使用该引用会导致未定义的行为。

要修复此问题,您可以一起删除所有引用({{1}和&&中的std::ostream&& out),并让它创建一个从临时对象初始化的新对象。

由于std::ostream&& o无法移动,因此上述操作无效。如果要保持多态性,则必须使用指针。如果那并不重要,则可以将所有std::ostream更改为std::ostream&&

std::ofstream