持有 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
被用作左值引用时,它的功能完全符合预期。
附加信息
- 编译器已尝试:
clang
、gcc
。
- 在平台上:Linux (4.19.0-11-amd64).
您创建的临时 std::ofstream{"testic"}
仅在构造函数调用期间存在。之后它被销毁并关闭文件,这意味着你留下了一个引用垃圾的引用。使用该引用会导致未定义的行为。
要修复它,您可以一起删除引用(std::ostream&& out
和 std::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();
}
#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
被用作左值引用时,它的功能完全符合预期。
附加信息
- 编译器已尝试:
clang
、gcc
。 - 在平台上:Linux (4.19.0-11-amd64).
您创建的临时 std::ofstream{"testic"}
仅在构造函数调用期间存在。之后它被销毁并关闭文件,这意味着你留下了一个引用垃圾的引用。使用该引用会导致未定义的行为。
要修复它,您可以一起删除引用(std::ostream&& out
和 std::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();
}