【问题标题】:Can [std::streampos] be converted to [size_t] implicitly?[std::streampos] 可以隐式转换为 [size_t] 吗?
【发布时间】:2017-01-18 08:14:37
【问题描述】:
#include <fstream>

int main()
{
    std::ifstream fin{ "" };
    size_t n = fin.tellg(); // ok
}

代码编译正常。但是,根据cppreference,我发现fin.tellg()std::fpos的一种类型,它并没有定义隐式转换为size_t的能力。

有什么解释吗?

【问题讨论】:

  • std::streampos 是一个整数类型,它可能与您系统上的size_t 兼容。仅仅因为没有保证,并不意味着它从不有效。
  • 如果文件非常大,你应该特别小心这种转换。
  • 理论上有可能std::fpos是64位,而size_t是32位。
  • @BoPersson basic_istream::tellg() 返回pos_type; pos_typeTraits::pos_typechar_traits&lt;char&gt;::pos_typestreamposstreamposfpos&lt;mbstate_t&gt;,这不是整数类型?
  • @BoB - 好吧,我错过了一步。 fpos 可隐式转换为 streamoff,即整数类型。

标签: c++ type-conversion standards filestream


【解决方案1】:

你是对的,它返回一个std::fpos。现在让我们看看它是如何定义的:

template<class _Statetype>
    class fpos {<...>}

fpos 也有一个转换运算符,用于转换为“流偏移”类型的streamoff 类型:

__CLR_OR_THIS_CALL operator streamoff() const
    {   // return offset
    return ((streamoff)(_Myoff + _FPOSOFF(_Fpos)));
    }

在我的机器上streamoff 恰好被定义为typedef _Longlong streamoff;,我相信它在你的机器上是类似的。这就是为什么它可以转换为type_t,但是没有什么可以阻止它大于type_t,所以要小心。

【讨论】:

    【解决方案2】:

    在您的平台上“确定”。不一定在所有平台上都可以。在实践中这是否意味着很多取决于具体情况。例如,在 32 位系统上,文件可能是 4GB 或更大,因此不适合 32 位 size_t,其中 std::fpos 是一个 64 位值,并且确实保存了文件的大小。

    如果n用于确定文件的长度等,如果您误判总大小 - 覆盖旧数据,或者如果您加载文件然后基于此保存,则可能会出现严重问题,您会丢失部分或全部数据。

    【讨论】:

    • 只是一个小提示:加载和保存文件的问题更加复杂 - 并且无法通过其他类型真正解决。原因是如果文件大小不适合 size_t 则文件内容不太可能适合内存。
    猜你喜欢
    • 1970-01-01
    • 2014-09-13
    • 2012-09-11
    • 2023-02-22
    • 1970-01-01
    • 2014-01-15
    • 2018-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多