【问题标题】:Where can I look up the definition of size_type for vectors in the C++ STL?在哪里可以查找 C++ STL 中向量的 size_type 定义?
【发布时间】:2010-09-18 14:02:28
【问题描述】:

将向量的size() 函数的结果转换为unsigned int 似乎是安全的。不过,我怎么能确定呢?我的文档不清楚 size_type 是如何定义的。

【问题讨论】:

  • 为什么要将结果转换为其他东西?您遇到类型不匹配的事实表明您的代码中有一些错误需要(或应该)修复(这就是 C++ 具有 STRONG 类型的原因)。不要尝试改变类型系统。
  • 如果他需要将容器的大小传递给一些使用无符号整数的现有代码怎么办?
  • 那么他就不走运了,因为在 64 位系统上,vector::size_type 可能相当合理地大于 unsigned int。
  • @JF:然后留下警告或修复您正在调用的代码。不要强制转换类型以删除警告,如果您的假设不成立,这只会在您迁移到新系统时破坏代码。
  • 或者删除警告但添加一个断言(最好是编译时),当假设失败时触发。例如,在 GCC 上,有一个旧技巧是声明一个 char[sizeof(unsigned int) - sizeof(size_type)],当差异为负时,它就会爆炸。

标签: c++ stl vector size


【解决方案1】:

不要假设容器大小的类型(或里面输入的任何其他内容)。

今天?

目前最好的解决方案是使用:

std::vector<T>::size_type

其中 T 是您的类型。例如:

std::vector<std::string>::size_type i ;
std::vector<int>::size_type j ;
std::vector<std::vector<double> >::size_type k ;

(使用 typedef 可以帮助更好地阅读)

迭代器和“内部”STL 容器的所有其他类型也是如此。

C++0x 之后?

当编译器能够找到变量的类型时,您将能够使用 auto 关键字。例如:

void doSomething(const std::vector<double> & p_aData)
{
    std::vector<double>::size_type i = p_aData.size() ; // Old/Current way

    auto j = p_aData.size() ;    // New C++0x way, definition
    decltype(p_aData.size()) k;  // New C++0x way, declaration
}

编辑:来自 JF 的问题

如果他需要将容器的大小传递给一些使用无符号整数的现有代码怎么办? ——JF

这是使用 STL 的一个常见问题:不做一些工作就无法做到。

第一个解决方案是将代码设计为始终使用 STL 类型。例如:

typedef std::vector<int>::size_type VIntSize ;

VIntSize getIndexOfSomeItem(const std::vector<int> p_aInt)
{
   return /* the found value, or some kind of std::npos */
}

第二个是自己进行转换,使用 static_cast,使用一个函数,如果值超出目标类型的范围,将断言(有时,我看到使用“char”的代码,因为,“你知道,索引永远不会超过 256" [我从记忆中引用])。

我相信这本身就是一个完整的问题。

【讨论】:

【解决方案2】:

根据标准,你不能确定。确切的类型取决于您的机器。不过,您可以查看编译器头文件实现中的定义。

【讨论】:

  • 我尝试查看我的标题。在遵循了相当多的通用定义之后,我在一个名为 xmemory 的文件中走到了死胡同,其中提到了 size_t 类型。根据我的 IDE,size_t 没有在任何地方定义!
  • 是的 - 阅读库标题(尤其是基于模板的标题)可能会很痛苦。
  • 至少在 gcc 上,实际定义 size_t (stddef.h) 的标头被埋在其他地方,远离通常的包含 (/usr/lib/gcc/.../include 而不是 / usr/include).
  • size_t 是标准的 C typedef。查看 cstddef,它可能会引导您访问 stddef.h (cplusplus.com/reference/clibrary/cstring/size_t.html)。事实是,像 NULL 一样,我认识的大多数程序员在使用 size_t 之前都不包含 cstddef。老实说,size_t 可能是一个无符号整数。
  • 一般来说,您应该使用 size_t,而您可能会想使用 unsigned int。对于这两种类型,您无法确定它们包含多少位,但在 size_t 的情况下,您可以确保它足够大以测量内存中事物的大小。
【解决方案3】:

我无法想象它在 32 位系统上不安全,但 64 位可能是个问题(因为整数仍然是 32 位)。为了安全起见,为什么不将变量声明为 vector::size_type 而不是 unsigned int?

【讨论】:

  • 这就是我所做的,但我仍然很好奇人们如何在 STL 上查找信息。
  • @Tommy :您已经拥有所需的所有信息。演员表不安全,您应该改用“vector::size_type”。或 size_t。如果您只是好奇它是什么,请询问编译器: cout
【解决方案4】:

C++ 标准仅规定 size_t 位于 中,这将标识符放在 中。我的Harbison & Steele 副本将size_t 的最小值和最大值放在 中。这应该让您了解您的平台需要多大的收件人变量。

您最好的选择是坚持使用足够大以在您的平台上容纳指针的整数类型。在 C99 中,这将是 intptr_tuintptr_t,也正式位于 中。

【讨论】:

    【解决方案5】:

    只要您确定系统上的 unsigned int 足够大以容纳向量中的项目数,您就应该是安全的 ;-)

    【讨论】:

    • 但这使得代码非门户。重点在于编写好的代码。
    • “只要 .. unsigned int .. 足够大”。这就是汤米想要弄清楚的。这是一个非答案。
    • 没错!每当您进行强制转换时,您都会覆盖类型系统,因此您需要知道自己在做什么。
    • @Aaron:我认为你误解了 JF 的回答。他指出,只要向量的实际运行时大小不大于 UINT_MAX,它就是安全的。这是一个比 size_type 的宽度不大于 unsigned int 的宽度更弱的条件。
    【解决方案6】:

    将其强制转换为 size_t 应该始终是安全的。 unsigned int 在大多数 64 位系统上不够用,甚至 unsigned long 在 Windows 上也不够用(它使用 LLP64 模型而不是大多数类 Unix 系统使用的 LP64 模型)。

    【讨论】:

      【解决方案7】:

      我不确定这将如何运作,因为我只是在思考,但是编译时断言(例如BOOST_STATIC_ASSERT() 或参见Ways to ASSERT expressions at build time in C)可能会有所帮助。比如:

      BOOST_STATIC_ASSERT( sizeof( unsigned int) >= sizeof( size_type));
      

      【讨论】:

      • 但是为什么。在发布代码时,假设一个类型在这里工作将无济于事。
      • 也许我误解了一些东西 - 如果编译器可以验证您希望大小进入的任何类型至少与您从 size() 获得的类型一样大,不是吗回答OP的问题?即使它不能自动解决问题
      • 请注意,我假设 OP 想要将 size_type 转换为 int,因为他将 size() 的结果传递给函数/方法/结构/任何想要 int 并且不受他控制的东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 2016-01-14
      • 1970-01-01
      相关资源
      最近更新 更多