gpt4 book ai didi

c++ - 为什么 C++ 标准文件流不更紧密地遵循 RAII 约定?

转载 作者:IT老高 更新时间:2023-10-28 12:46:43 27 4
gpt4 key购买 nike

为什么 C++ 标准库流使用与对象生命周期分离的 open()/close() 语义?在销毁时关闭可能在技术上仍会使类成为 RAII,但获取/释放独立性会在句柄可以指向任何内容但仍需要运行时检查才能捕获的范围中留下漏洞。

为什么库设计者选择他们的方法而不是只在引发失败的构造函数中打开?

void foo() {
std::ofstream ofs;
ofs << "Can't do this!\n"; // XXX
ofs.open("foo.txt");

// Safe access requires explicit checking after open().
if (ofs) {
// Other calls still need checks but must be shielded by an initial one.
}

ofs.close();
ofs << "Whoops!\n"; // XXX
}

// This approach would seem better IMO:
void bar() {
std_raii::ofstream ofs("foo.txt"); // throw on failure and catch wherever
// do whatever, then close ofs on destruction ...
}

这个问题的更好措辞可能是为什么访问未打开的 fstream 是值得的。通过句柄生命周期控制打开文件的持续时间在我看来根本不是负担,实际上是一种安全优势。

最佳答案

虽然其他答案都是有效且有用的,但我认为真正的原因更简单。

iostreams 的设计比许多标准库的设计要古老得多,并且早于异常的广泛使用。我怀疑为了与现有代码兼容,异常的使用是可选的,而不是打开文件失败的默认设置。

另外,您的问题仅与文件流真正相关,其他类型的标准流没有 open()close() 成员函数,所以如果无法打开文件,它们的构造函数不会抛出:-)

对于文件,您可能需要检查 close() 调用是否成功,以便知道数据是否已写入磁盘,这是一个很好的理由在析构函数中执行此操作,因为当对象被销毁时,对它做任何有用的事情都为时已晚,而且您几乎肯定不想从析构函数中抛出异常。因此 fstreambuf 会在其析构函数中调用 close,但如果您愿意,您也可以在销毁之前手动执行此操作。

无论如何,我不同意它不遵循 RAII 约定...

Why did the library designers choose their approach over having opening only in constructors that throw on a failure?

注意RAII 并不意味着除了获取资源的构造函数之外,您不能拥有单独的 open() 成员,或者您不能> 在销毁之前清理资源,例如unique_ptr 有一个 reset() 成员。

此外,RAII 并不意味着您必须抛出失败,或者对象不能处于空状态,例如unique_ptr 可以用空指针构造或默认构造,因此也可以不指向任何内容,因此在某些情况下,您需要在取消引用之前对其进行检查。

文件流在构造时获取资源并在销毁时释放它 - 就我而言,这就是 RAII。你反对的是需要检查,这有两阶段初始化的味道,我同意这有点臭。但这并不意味着它不是 RAII。

过去我用 CheckedFstream 类解决了这个问题,这是一个简单的包装器,添加了一个功能:如果无法打开流,则抛出 cosntructor。在 C++11 中就这么简单:

struct CheckedFstream : std::fstream
{
CheckedFstream() = default;

CheckedFstream(std::string const& path, std::ios::openmode m = std::ios::in|std::ios::out)
: fstream(path, m)
{ if (!is_open()) throw std::ios::failure("Could not open " + path); }
};

关于c++ - 为什么 C++ 标准文件流不更紧密地遵循 RAII 约定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25624774/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com