【问题标题】:size_t vs int in C++ and/or CC++ 和/或 C 中的 size_t 与 int
【发布时间】:2010-11-02 22:01:17
【问题描述】:

为什么在 C++ 容器中,它返回 size_type 而不是 int?如果我们正在创建自己的结构,是否也应该鼓励我们使用size_type

【问题讨论】:

标签: c++ c size-type


【解决方案1】:

一般来说,当您测量某物的大小时,应该使用size_tsize_t 只需要表示 0 到 SIZE_MAX 字节之间,SIZE_MAX 只需要 65,535 个字节,这真的很奇怪......

来自 C++ 和 C 标准的其他有趣的限制是:

  • sizeof() 的返回类型是size_t,它是一个无符号整数
  • operator new() 将要分配的字节数作为size_t 参数
  • size_t<cstddef> 中定义
  • SIZE_MAX 在 C99 的 <limits.h> 中定义,但在 C++98 中没有提及?!
  • size_t 不包括在基本整数类型列表中,所以我一直认为size_t 是基本类型之一的类型别名:charshort int、@987654337 @ 和 long int

如果您计算字节数,那么您绝对应该使用size_t。如果您正在计算元素的数量,那么您可能应该使用size_t,因为这似乎是 C++ 一直在使用的。在任何情况下,您都不想使用 int - 如果您使用的是 TR1,至少使用 unsigned longunsigned long long。或者......甚至更好...... typedef 无论你最终使用什么到 size_type 或只包括 <cstddef> 并使用 std::size_t

【讨论】:

  • size_t 不仅需要达到 64k,还需要能够表示任何对象的大小(在 C 标准中,我认为,所以也许 C++ 标准没有提到它)。几乎任何编译器都必须使其大小与指针相同。并不像看起来那么奇怪。
  • 是的,它需要表示内存中任何单个对象分配的大小。不需要表示最大对象数,只需表示最大可表示对象消耗的字节数。将 size_t 的范围与可寻址内存进行比较并不是真正有效的比较,除非您可以在单个对象中分配整个可寻址内存范围。
  • 因此“几乎所有编译器”。现在我们大多拥有未分段的内存架构,并且希望映射大文件,并且大多数编译器都实现了 intptr_t(来自 C99)或类似的,人为地将对象的大小限制为比可以跨越的更小的整数类型并没有太大的意义。地址空间。所以这就是为什么我不认为 C++ 实现使用 size_t 作为 size_type 的原因。 64k SIZE_MAX 最小值如此之低的原因可能只是为了支持 16 位架构:您不会期望 32 位以上的编译器实际做到这一点。
【解决方案2】:

可能有几个原因:

  • 类型 (size_t) 可以定义为该平台上最大的无符号整数。例如,它可能被定义为 32 位整数或 64 位整数或其他能够存储大长度无符号值的东西
  • 为了在读取程序时明确该值是一个大小,而不仅仅是一个“常规”int

如果您正在编写一个专为您和/或一次性使用的应用程序,您可能可以使用基本的 int。如果您正在编写库或其他内容,size_t 可能是更好的选择。

【讨论】:

  • 想象一个简单的新启动的 64 位操作系统,没有膨胀软件,您可以使用new char[6 gigs],如果您有足够的 RAM 或交换空间,它就会工作。现在,您如何使用 int 进行管理?这就是size_t背后的原因。
【解决方案3】:

有些答案比必要的更复杂。 size_t 是一种无符号整数类型,保证足够大以存储内存中任何对象的字节大小。在实践中,它总是与指针类型的大小相同。在 32 位系统上,它是 32 位。在 64 位系统上,它是 64 位。

【讨论】:

  • 为了好玩:我记得一个潜在的反例相同大小的指针/size_t。在 DOS 16 位段中:16 位偏移方案。指针是 32 位的。 size_t 被限制为 16 位。希望这样的阴谋不要再发生了。
  • 这实际上是正确的。段/偏移量实际上不是 C 意义上的“指针”,因为您无法自然地对其进行算术运算(尽管编译器非常擅长在“巨大”模式下使用生成的代码隐藏它)。您可以通过偏移量解决的最大问题确实是 65536 字节。
【解决方案4】:

stl 中的所有容器都有不同的 typedef。例如,value_type 是元素类型,size_type 是数字存储类型。通过这种方式,容器是基于平台和实现的完全通用的。

如果您要创建自己的容器,您也应该使用size_type。通常这样做

typedef std::size_t size_type;

如果你想要一个容器的大小,你应该写

typedef vector<int> ints;
ints v;
v.push_back(4);
ints::size_type s = v.size();

好在以后如果想使用列表,只要把typedef改成

typedef list<int> ints;

它仍然可以工作!

【讨论】:

    【解决方案5】:

    我假设你的意思是“size_t”——这是一种表示无符号整数(只能是正数,不能是负数)的方式——它对容器的大小有意义,因为你不能有一个数组大小为-7。我不会说您必须使用 size_t 但它确实使用您的代码向其他人表明“这里的数字始终是正数”。它还为您提供更大范围的正数,但这可能并不重要,除非您有一些非常大的容器。

    【讨论】:

    • size_t 和 size_type(尽管它们通常具有相同的值)是两个不同的东西。
    【解决方案6】:

    C++ 是一种可以在不同硬件架构和平台上实现的语言。随着时间的推移,它已经支持 16 位、32 位和 64 位架构,未来可能还会支持其他架构。 size_type 和其他类型别名是库将程序员/代码与实现细节隔离开来的方式。

    假设size_type 在 32 位机器上使用 32 位,在 64 位机器上使用 64 位,如果您在需要的地方使用了 size_type,相同的源代码可能会更好地工作。在大多数情况下,您可以假设它与unsigned int 相同,但不能保证。

    size_type 用于表示 STL 容器的容量,如std::vector,而size_t 用于表示 C/C++ 中对象的字节大小。

    【讨论】:

      【解决方案7】:

      int 在规范中不保证为 4 个字节,因此它们不可靠。是的,size_type 比 ints 更受欢迎

      【讨论】:

      • size_t 是否保证为任何特定尺寸?
      • 奇怪的是,它们只需要能够表示 0 到 65,535 之间的值。标准中的相关条款是C99中的7.18.3。实际限制在 中定义的 0 和 SIZE_MAX 之间
      • @DShawley int 只能保证最多可以表示 32,767。所以我不确定你的意思是什么。
      【解决方案8】:

      size_t 是无符号的,因此即使它们都是 32 位,它与不合格的 int 并不完全一样。我不确定他们为什么添加该类型,但在今天的许多平台上sizeof (size_t) == sizeof (int) == sizeof (long),所以您选择哪种类型取决于您。请注意,这些关系不受标准的保证,并且随着 64 位平台的加入而迅速过时。

      对于您自己的代码,如果您需要在概念上表示某种“大小”并且永远不能为负数,size_t 将是一个不错的选择。

      【讨论】:

        【解决方案9】:
        void f1(size_t n) {
            if (n <= myVector.size()) { assert(false); }
            size_t n1 = n - myVector.size(); // bug! myVector.size() can be > n       
            do_stuff_n_times(n1);
        }
        
        void f2(int n) {
            int n1 = n - static_cast<int>(myVector.size());
            assert(n1 >= 0);
            do_stuff_n_times(n1);
        }
        

        f1() 和 f2() 都有相同的错误,但在 f2() 中检测问题更容易。对于更复杂的代码,无符号整数算术错误并不那么容易识别。

        我个人对所有尺寸都使用有符号整数,除非应该使用无符号整数。我从来没有遇到过我的大小不适合 32 位有符号整数的情况。在使用无符号 32 位整数之前,我可能会使用 64 位有符号整数。

        使用有符号整数来表示大小的问题是代码中有很多从size_tintstatic_cast

        【讨论】:

        • 这实际上不是一个很好的点,因为assert(n &gt;= myVector.size()) ; 可以完美地检测到错误。
        猜你喜欢
        • 2010-10-04
        • 1970-01-01
        • 1970-01-01
        • 2010-09-13
        • 1970-01-01
        • 2020-08-16
        • 2021-10-17
        • 2011-09-28
        • 1970-01-01
        相关资源
        最近更新 更多