【问题标题】:Get the index of a std::vector element given its address获取给定地址的 std::vector 元素的索引
【发布时间】:2011-12-30 20:08:46
【问题描述】:

假设我有一个 std::vector 并且我通过某种方式获得了第 n 个元素的地址。 给定我的 std::vector 的基地址,是否有一种简单的方法(比遍历向量更快)来获取元素出现的索引?假设我确定元素在向量中。

【问题讨论】:

    标签: c++ stl stdvector


    【解决方案1】:

    距离(xxx.begin(), theIterator);

    以上仅适用于vector::iterator。如果你只有一个指向元素的原始指针,你必须这样使用它:

    距离(&v[0], theElementPtr);

    【讨论】:

    • 他没有迭代器,他有内存地址。不能保证向量迭代器是原始指针,实际上有几个实现不是。
    • 指针和迭代器是有区别的,他指定了一个迭代器。如果他可以重构,这是一个很好的建议。
    • 对于向量,迭代器和指针大部分是可以互换的。如果您传递元素指针而不是迭代器,则距离函数应该可以工作。
    • -1 元素地址不是向量迭代器(一般来说,它可能在某个实现中)
    • 元素的地址在技术上并不是按类型划分的迭代器,但是指向向量的指针具有实现随机访问迭代器的正确行为。在这种情况下,正确使用距离是 distance(&v[0], theElementPtr) ,这将按照下面的答案进行减法。
    【解决方案2】:

    既然你知道元素在向量中,并且向量保证它的存储是连续的,你可以这样做:

    index = element_pointer - vector.data();
    

    或

    index = element_pointer - &vector[0];
    

    请注意,从技术上讲,连续保证是在 C++03 中引入的,但我还没有听说过 C++98 实现碰巧没有遵循它。

    【讨论】:

    • 请注意,这只适用于 C++03/C++11std::vectors 和 C++11std::strings
    • @Adrian,C++98 并不能完全保证向量的所有元素都将驻留在连续的内存中。实际上,它在所有 C++ 版本中都是安全的,但只有标准的后续版本才能保证。
    • 没错,我会补充的。
    • 不包括向量 - 在 23.1.1.12 中描述了 a[n] 的操作语义 - 它说它与 *(a.begin() + n) 的向量和双端队列相同 -这必须保证两者的连续内存 - 不是吗? (虽然它不完全是简单的英语:-)
    • @Adrian Cornish:C++03 专用的vector<bool> 不是容器,它不满足概念。由于 C++11 vector<bool> 是一个常规的解压容器。
    【解决方案3】:

    是的 - 因为向量保证所有元素都在一个连续的内存块中,你可以使用指针算法来找到它

    #include <iostream>
    #include <vector>
    
    int main(int argc, char *argv[])
    {
       std::vector<int> vec;
    
       for(int i=0; i<10; ++i)
       {
          vec.push_back(i);
       }
    
       int *ptr=&vec[5];
       int *front=&vec[0];
    
       std::cout << "Your index=" << ptr-front << std::endl;
       return 0;
    }
    

    【讨论】:

      【解决方案4】:

      在学习的路上,我做了以下笔记:

      #include <iostream>
      #include <vector>
      
      int main() {
          std::vector<std::string> words={"This","is","just","a","trial!"};
          size_t i; //using the contiguous property of a vector:
          for (auto const& elem : words) {
              i = &elem - &*words.begin();// or
              i = &elem - &words.front();// or 
              i = &elem - words.data();// or
              i = std::addressof(elem) - std::addressof(words[0]); 
              if(std::addressof(elem) == &words.front())
                std::cout << elem <<" (at"<<&elem<<") relative to ("<< &words[0] << ") takes position @#"<<i<< std::endl;
              else std::cout << elem <<" (at"<<&elem<< ") takes position @#"<<i<< std::endl;
          }
          return 0;
      }
      

      试运行here。 有待进一步研究(或向大师学习)哪种方法是最安全/最安全和/或最有效的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-30
        • 2013-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-12
        相关资源
        最近更新 更多