【问题标题】:C++ vector size typesC++ 向量大小类型
【发布时间】:2011-11-29 23:34:15
【问题描述】:

我刚开始学习 C++,有一个关于向量的问题。 我正在阅读的书指出,如果我想提取 double 类型的向量的大小(例如),我应该这样做:

vector<double>::size_type vector_size;
vector_size = myVector.size();

而在 Java 中我可能会这样做

int vector_size;
vector_size = myVector.size();

我的问题是,为什么会有一个名为 vector::size_type 的类型?为什么 C++ 不只使用 int?

【问题讨论】:

  • 这个问题http://stackoverflow.com/q/131803/72178有答案。
  • 在 C++11 中,你可以说 auto vector_size = myVector.size(); 并少一些担心 ;)
  • @FredOverflow 如果您将vector_size 初始化为0 但您打算将其用作vector&lt;double&gt;::size_type,这并不好。
  • @BrianGordon 我不明白你的反对意见。如果myVectorstd::vector&lt;double&gt; 类型,而你写auto vector_size = myVector.size(); 那么vector_sizestd::vector&lt;double&gt;::size_type 类型,无论向量是否为空。请澄清。
  • 如果你有for(std::vector&lt;double&gt;::size_type i=0; i&lt;myVector.size(); i++)那么auto不能用来声明i

标签: c++ vector int


【解决方案1】:

Java 没有无符号整数类型,所以它们必须与 int 一起使用。

相反,C++ 会在适当的地方使用它们(负值是无意义的),典型的例子是数组之类的长度。

【讨论】:

  • 标准使用size_t而不是int的原因是因为在一些较小的机器上,int不够大(而去long会招致性能损失)。在这里使用无符号类型通常被认为是一个缺陷,因为 C 和 C++ 中的无符号类型以某种有趣的方式工作。 (基本上,像abs(i1 - i2) 这样的表达式应该正确地给出两种索引类型之间的距离。如果i1i2 是无符号的,则不会。)
【解决方案2】:

C++ 是一种用于编写库的语言*,让作者尽可能笼统是其主要优势之一。与其规定标准容器使用任何特定的数据类型,更通用的方法是规定每个容器公开一个size_type 成员类型。这允许更大的灵活性和通用性。例如,考虑以下通用代码:

template <template <typename...> Container, typename T>
void doStuff(const Container<T> & c)
{
  typename Container<T>::size_type n = c.size();
  // ...
}

此代码适用于任何容器模板(可以使用单个参数实例化),我们不会对代码的用户施加任何不必要的限制。

(实际上,大多数大小类型都会解析为std::size_t,而这又是一个无符号类型,通常是unsigned intunsigned long——但我们为什么要知道这一点?)

*) 我不确定 Java 的相应语句是什么。

【讨论】:

  • @Kerrek 除非您使用的是 64 位系统,而 std::size_t 可能是 64 位类型。
  • @xanatos:是的。出于好奇,也许我们应该挖掘一些常见的 typedef。
【解决方案3】:

我个人对此的感觉是,它是为了更好的代码安全性/可读性。

对我来说int 是一个没有特殊含义的类型:它可以给苹果、香蕉或任何东西编号。

size_type,可能是typedef for size_t 的含义更强:它表示大小,以字节为单位。

也就是说,更容易知道变量的含义。当然,按照这个原理,不同的单位可能有很多不同的类型。但是“缓冲区大小”确实是一种常见情况,因此它应该以某种方式使用专用类型。

另一方面是代码可维护性:如果容器突然将其size_typeuint64_t 更改为unsigned int,例如,使用size_type,您不必在依赖它的每个源代码中更改它.

【讨论】:

    【解决方案4】:

    C++ 标准说容器的size_type 是无符号整数类型,但它没有指定是哪一个;例如,一种实现可能使用unsigned int,另一种可能使用unsigned long

    C++ 不像 Java 那样“屏蔽”特定于平台的实现细节。 size_type 别名有助于保护您的代码免受此类细节的影响,因此无论应该使用什么实际类型来表示向量的大小,它都能正常工作。

    【讨论】:

      【解决方案5】:

      您正在阅读的书指出,如果您想提取 double 类型的向量的大小(例如),您应该执行以下操作:

          vector<double>::size_type vector_size;
          vector_size = myVector.size();
      

      而在 Java 中你可能会这样做

          int vector_size;
          vector_size = myVector.size();
      

      两者都是 C++ 中的劣等选项。第一个是非常冗长和不安全的(主要是由于隐式促销)。第二个是冗长且极其不安全的(由于数字范围)。

      在 C++ 中,做

          ptrdiff_t const vectorSize = myVector.size();
      

      注意

      • ptrdiff_t,来自stddef.h 标头,是保证足够大的有符号类型。

      • 在声明中完成初始化(这是更好的 C++ 风格)。

      • 相同命名约定已应用于这两个变量。

      总之,做正确的事更短更安全。

      干杯,

      【讨论】:

      • 我不确定我理解为什么第一种方法不安全。隐式促销是什么意思?
      • 除非他们已经在 C++11 中修复它,否则ptrdiff_t 保证足够大。可能有大小无法在 ptrdiff_t 中表示的对象。
      • @James:这里没有足够的空间来讨论 char 的数组在 16 位地址空间中如何可能太大。 32 位地址空间中 char 的 3 GiB 数组的答案是标准不支持它(ptrdiff_t 需要足够大),所以如果你必须拥有那个野兽,请特别处理它。就个人而言,我从未遇到过char 的3 GiB 数组。 :-)
      • @AlfP.Steinbach 我也从来不需要 char 的 3 GiB 数组,但我使用了支持它们的 32 位实现(Solaris 下的 Sun CC,Linux 下的 g++,32位电脑)。 C 标准绝对允许指针减法溢出(导致未定义的行为),据我所知,C++ 标准只是将责任推给了 C 标准。
      • @James:在我看来,C++11 中的 5.7 和 18.2 之间存在争议。 5.7 说溢出是可能的,18.2 说ptrdiff_t“可以保存数组对象中两个下标的差异,如 5.7 中所述”。这与 C89/C99 中的文字不同,它只是说ptrdiff_t 是指针减法结果的类型,而不是它通常可以保存该值。在我看来,好像写它的人都希望在 C++11 中解决这个问题,但是 18.2/6(对于 any 对象来说足够大)和 /5 之间的语言仍然存在差异(一个数组对象)。
      猜你喜欢
      • 1970-01-01
      • 2015-11-22
      • 2021-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-02
      • 1970-01-01
      • 2017-02-15
      相关资源
      最近更新 更多