【问题标题】:What is the standard way in C++11 to access the pointer to element n in a std::vector?C ++ 11中访问std :: vector中元素n的指针的标准方法是什么?
【发布时间】:2019-09-24 02:27:35
【问题描述】:

C++11 中访问std::vector 中元素 n 的指针的标准方法是什么?

vec.data() + n

&vec[n]

想到了。

【问题讨论】:

标签: c++ c++11 vector std c++-standard-library


【解决方案1】:

“标准方式”不存在,您的问题中的两种方式都可以正常工作,并且这里没有与性能相关的问题。但可能还有其他情况需要考虑:错误处理、静态分析警告、operator & 可能重载、将std::vector 替换为不同类型的能力。

  1. 静态分析。当你使用第一个版本时,clang-tidy throws

    warning: do not use pointer arithmetic [cppcoreguidelines-pro-bounds-pointer-arithmetic]
    vec.data() + 1;
               ^
    

    在你身上(当然,这个特定的检查是启用的)。不是最严重的问题,但为了完整起见,当您使用第二个版本时不会出现此警告。

  2. 用另一种连续容器类型替换std::vector,或者如果您编写模板(您基本上希望对您的类型的要求尽可能小)。那么,

    auto *ptr = vec.data() + n;
    

    要求.data() 成员函数存在并执行您期望它执行的操作。示例:Llvm 的SmallVector 模板(针对更少的分配进行了优化)没有data(),但它确实有operator []。我认为由于这个原因,

    auto *ptr = &vec[n];
    

    更可取。诚然,另一种向量类型同样可以重载 operator()(...) 而不是 [](或根本没有重载运算符),但这可能比 .data() + n 方法更容易在某些函数中修复。

因此,让我考虑以下两个问题的第二个版本。

  1. 错误处理:当需要检查向量的大小是否至少为n + 1时:

    auto *ptr = vec.size() > n ? &vec[n] : nullptr;
    

    需要与烘焙到std::vector 本身的检查进行比较:

    try {
        auto *ptr = &vec.at(n);
         // Do stuff with ptr
    } catch (const std::out_of_range&) { /* ... */ }
    

    这里哪一个更好在很大程度上取决于项目和上下文特定的情况(是否启用了例外,向量的大小是否是某个范围的先决条件等),因此通常不可能选择一个。了解这些选项是件好事。

  2. 重载operator &。在应该在不同上下文中重用的代码中,这样做并没有什么坏处

    auto *ptr = std::addressof(vec[n]);
    

    因为这很好地处理了这个运算符的邪恶重载。

结合以上场景,选择最适合具体情况的方法。

【讨论】:

  • 这个详尽的答案使其他答案变得多余。 +1。
  • 注意:使用&vec[n] 获取指向end() 元素的指针是未定义的行为。为此需要使用vec.data()+n
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-15
  • 2011-03-18
  • 2018-12-25
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多