gpt4 book ai didi

c++ - gzstream lib打开不存在的文件

转载 作者:行者123 更新时间:2023-11-30 02:42:25 25 4
gpt4 key购买 nike

我正在尝试在 xcode 6.1、libz.1.dylib 下使用 gzstream 1.5 进行 ios 开发。

这个库是很久以前写的。

我发现

class igzstream : public gzstreambase, public std::istream

应该
class igzstream : public gzstreambase, public virtual std::istream

ogzstream 也一样。

因为如果文件不存在,第一个变体在初始化后为 good() 返回 true。 AFAIK 这是因为两个祖先 std::ios。

我想知道这真的是一个错误,为什么还没有修复!

最佳答案

C++ 标准定义了名称 std::istream作为 std::basic_istream<char> 的 typedef在 [lib.iostream.format] 中,它实际上源自 std::basic_ios<char> ,根据 [lib.istream]。
另一方面,gzstreambase实际上源自 std::ios ,在 [lib.iostream.forward] 中定义为 std::basic_ios<char> 的 typedef .所以两个继承分支都与std::ios有虚拟继承关系。 (又名 std::basic_ios<char>)。

如果你的标准库实现没有被破坏,你不应该得到两个 std::ios igzstream 中的子对象,但是通过更改基类初始化的顺序来声明基类 virtual 会产生进一步的后果。

igzstream 类:公共(public) gzstreambase,公共(public) std::istream

首先初始化虚拟基类(甚至是间接基类),所以 std::ios是第一个被初始化的,它依次初始化 std::ios_base (自身的非虚拟基类)。然后非虚拟基类按从左到右的顺序初始化,所以gzstreambase首先,然后 std::istream .

igzstream 类:公共(public) gzstreambase,虚拟公共(public) std::istream

首先初始化虚拟基类(甚至是间接基类),所以 std::ios是第一个被初始化的,它依次初始化 std::ios_base (自身的非虚拟基类)。然后std::istream已初始化,因为它仍然是另一个虚拟基类,但需要 std::ios ,最后是 gzstreambase .

考虑到这一点,您可以确定来自 std::istream 的虚拟派生似乎是一个非常糟糕的主意,因为 igzstream 的构造函数将其名为 buf 的 gzstreambuf 成员的地址传递给 std::istream 的构造函数。在继承的成员 buf 被初始化之前的对象。

可能您的问题的原因是 gzstreambase(consth char *, int)来电std::ios::init() ,以及 std::istream根据 [lib.istream.cons],构造函数的行为就好像它一样。函数std::ios::init已记录以在良好状态下初始化流。因此,如果 istream 子对象在 gzstreambase 对象之后初始化,则 ios 基础对象的第二个 init 确实应该清除错误标志。这实际上看起来像是 gzstream 库中的一个错误。获得正确的构造顺序(首先是 gzstreambuf,其次是 istream,然后尝试打开文件)似乎是一个完全不简单的问题。原始版本具有“gzstreambuf,open,istream”,其中 istream 破坏了打开失败,而您建议的修复具有“istream,gzstreambuf,open”,其中 istream 获取尚未构建的 streambuf 的地址。

一种解决方法是不使用 gzstream 的开放构造函数,但我会考虑一个好的解决方案来修复开放构造函数,并会在我得到结果后立即编辑答案。

根据您询问的对象,多个初始化调用都可以(http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#135 的通常解释)或未定义(http://article.gmane.org/gmane.comp.lib.boost.devel/235659)。在 Microsoft 编译器上,多次调用 init 会导致内存泄漏,并且 Dinkumware(提供 Microsoft 使用的 I/O 库)坚持认为标准没有指定多次调用的行为,因此它是未定义的行为。

因此,对于实际的便携行为,不要重复调用 init。然而这就是在 gzstream 中发生的事情。这实际上是 C++ 中多重继承的反对者似乎是正确的情况之一。你确实需要继承 std::istream 才能提供“istream 接口(interface)”,而另一方面,你不需要继承 std::istream,因为它的构造函数做了你不想要的事情。如果 std::istream 只是“一个接口(interface)”,您可以在从 gzstreambase 派生实现的同时实现它,而不会出现问题。

在这种情况下,我看到的唯一解决方案是删除执行打开的 gzstreambase 构造函数,并将打开调用放入 igzstream 和 ogzstream 构造函数中(从而复制对打开的调用)。通过这种方式,可以依赖在 istream/ostream 构造函数中调用一次且仅调用一次 init。

关于c++ - gzstream lib打开不存在的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27076809/

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