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

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

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

vec.data() + n

&vec[n]

想到了。

最佳答案

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

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

    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];
    

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

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

  1. 错误处理:当您需要检查 vector 的大小是否至少为 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&) { /* ... */ }
    

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

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

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

    因为这与该运算符的恶意重载配合得很好。

结合上述场景,选择最适合特定情况的方法。

关于c++ - C++11 中访问指向 std::vector 中元素 n 的指针的标准方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56005421/

相关文章:

具有继承模板的C++调用函数

c++ - 递归复制链表

c++ - 使用 C++11 可变参数模板在编译时快速排序

c++11 - 可变参数类型定义,或 "Bimaps done the C++0x way"

c++ - 调用 operator== 时,MSVC 不会执行用户定义的到 std::nullptr_t 的隐式转换

c++ - VBA 中的 "Invalid use of New Keyword"使用用 C++ 编写的旧 com 对象

c++ - 使用可变参数模板的 mixin 继承的可见性规则

windows - 如何查找发生运行时错误的行 - Visual C++

c++ - 构造函数中的 vector 初始化

对象被推回并且函数退出后,C++ vector 推回崩溃