持有 std::ostream 右值成员时的奇怪行为

Weird behaviour when holding std::ostream rvalue member

#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 被用作左值引用时,它的功能完全符合预期。

附加信息

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

要修复它,您可以一起删除引用(std::ostream&& outstd::ostream&& o 中的 &&)并让它创建一个初始化的新对象从临时.

以上方法无效,因为 std::ostream 无法移动。如果要保持多态性,则必须改用指针。如果那不重要,您可以将所有 std::ostream&& 更改为 std::ofstream:

class A {
 private:
  std::unique_ptr<std::ostream> out;

 public:
  A(std::unique_ptr<std::ostream> o) : out(std::move(o)) {
    out->write("test", 4);
  }

  void writeTest2() {
    out->write("test2", 5);
    out->flush();
  }
};

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