【问题标题】:How can I get sizeof a vector::value_type?我怎样才能得到一个vector::value_type的sizeof?
【发布时间】:2014-02-12 23:31:10
【问题描述】:

我想获取向量中包含的类型的sizeof。这是我尝试过的:

#include <iostream>
#include <vector>

int main()
{
    std::vector<uint> vecs;
    std::cout << sizeof(vecs.value_type) << std::endl;
    return 0;
}

据我了解,这应该是正确的。但是,当使用 GCC 4.8.1 编译时,我得到的是:

test-sizeof.cpp:在函数“int main()”中:
test-sizeof.cpp:7:27:错误:“std::vector::value_type”的使用无效
  std::cout 

我做错了什么?如何获取包含类型的大小?

【问题讨论】:

  • 使用std::vector&lt;uint&gt;::value_type
  • sizeof(std::vector&lt;uint&gt;::value_type)sizeof(decltype(vecs)::value_type)
  • 为什么不简单地sizeof(vecs[0])
  • @HagenvonEitzen 即使向量的元素为零,这也能工作吗?
  • 是的,因为不计算操作数。 (是的,我迟到了。:|)

标签: c++ c++11 vector sizeof value-type


【解决方案1】:

cmets 说得差不多了:如果你知道向量的类型,你可以使用sizeof(std::vector&lt;uint&gt;::value_type)。否则使用sizeof(decltype(vecs)::value_type)

decltype 是一个神奇的 C++11 构造,计算其参数的类型,所以代码

int i;
float f;

decltype(i) j;
decltype(f) g;

一样
int i;
float f;

int j;
float g;

仅将. 运算符用于字段和方法(从技术上讲,它也可以用于静态变量,但被认为是不好的做法)。对于其他任何内容,例如静态变量、内部类或类范围模板参数或类型定义(例如 value_type),请使用范围解析运算符 ::

【讨论】:

    【解决方案2】:

    成员访问运算符.只能用于访问类的数据成员和成员函数,不能访问类型名等其他嵌套名称。您需要范围解析运算符:: 来访问它们,并且只能应用于类名(或别名),而不是类类型的对象:

    std::vector<uint>::value_type
    

    在 C++11 或更高版本中,decltype 可以为您提供类型名称,如果您有一个对象并且无法方便地访问该类型:

    decltype(vecs)::value_type
    

    【讨论】:

    • Nitpick nazi 说:嵌套类型类的成员 §9.2/1 “类的成员是数据成员、成员函数 (9.3)、嵌套类型和枚举器” ,但它们被明确排除在成员访问表达式 §5.2.5/4 “如果 E2 是嵌套类型,则表达式 E1.E2 格式错误。”
    • @Casey:谢谢,我不确定“成员”的确切定义。现在答案更正确了。
    【解决方案3】:

    3.4.3 限定名称查找 [basic.lookup.qual]

    1 类或命名空间成员或枚举器的名称可以是 在 :: 范围解析运算符 (5.1) 之后引用 表示其类、命名空间或 枚举。如果 :: 范围解析运算符在 嵌套名称说明符前面没有 decltype 说明符,查找 :: 前面的名称只考虑命名空间、类型、和 特化为类型的模板。如果找到的名称没有 指定命名空间或类、枚举或依赖类型, 程序格式不正确。

    在这种情况下,您正在从类模板特化 std::vector&lt;uint&gt; 访问一个 type 成员,您需要通过以下方式进行:

    std::vector<uint>::value_type
    

    如果您实际上在模板代码中并且想要例如访问相同的嵌套类型,您需要在其前面加上关键字typename,如下所示:

    typename std::vector<T>::value_type
    

    在 C++11 中,您可以使用sizeof(decltype(vecs)::value_type)sizeof(decltype(vecs.back())),如果您不知道类型的确切名称但知道如何通过@987654328 之类的成员函数访问它们,则后者很方便@。

    注意:正如@Casey 在 cmets 中指出的那样,decltype 需要剥离引用才能获取类型本身,但对于 sizeof 而言,这并不重要。

    【讨论】:

    • 回复。最后一段,.-&gt; 都可以用来访问static 数据成员或函数,它们是 成员。它只是不能用于访问类型。
    • @DavidRodríguez-dribeas tnx,我删除了该部分,因为我不想深入了解有关 . 的所有细节。
    • ...和枚举器!让我们不要忽视可怜的手无寸铁的枚举员。
    • Nit: decltype(vecs.back())decltype(vecs)::value_type&amp; 并且需要使用 std::remove_referencestd::decay 剥离才能得到纯类型。
    • 由于sizeof() 可以传递一个表达式,而不仅仅是一个类型,所以没有必要使用decltype() 将一个表达式转换为它的类型。例如,sizeof('x') 是有效的,不需要写sizeof(decltype('x'))。这导致我认为是对原始问题的最佳答案。使用sizeof(vecs[0]) 获取大小。在这种未经评估的情况下使用std::vector::operator[] 是完全安全的。它非常简洁,适用于向量、其他容器,甚至 C 数组或指针。例如,在一个模板中,vecs 的类型除了向量之外可能还有很多。
    【解决方案4】:

    我更喜欢简洁的:

    sizeof(vecs[0])
    

    乍一看似乎不安全,因为当vecs 是零长度向量时会发生什么?

    对于此示例,在值类型上调用 sizeof() 运算符的参数时,sizeof() 运算符在编译时执行,因此 vecs[0] 永远不会导致段错误或崩溃。

    附言sizeof() 仅在参数是可变长度数组(来自 C 或 GNU C++ 扩展)时在运行时评估

    【讨论】:

      猜你喜欢
      • 2015-12-15
      • 2015-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-27
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      相关资源
      最近更新 更多