我可以得到索引直接从指针的向量元素在c++

Can I get index directly from pointer of vector element in C++?

本文关键字:向量 元素 c++ 指针 索引 我可以      更新时间:2023-10-16

我有一个大的矢量容器,可以容纳大约300.000个对象。我也有指向这些对象的指针

是否有任何快速的方法来获得对象的索引在矢量使用指针?

由于向量是按顺序组织的,因此可以通过从指向元素的指针中减去指向初始元素的指针来获得索引:

std::vector<MyObject> vect;
MyObject *ptrX = ... // Pointer to element in question
ptrdiff_t index = ptrX - &vect[0];
在这种情况下,

迭代器头应该是有用的。

让我们假设你有这样的内容:

using Vector = std::vector<Foo>;
using Iterator = Vector::iterator;
Vector big_vector;

现在你有了一个对象的迭代器:

Iterator p_obj = get_Theobj(big_vector);

索引可以很容易地在距离上得到:

auto index = std::distance(big_vector.begin(), p_obj);
// Note: index's type is a `difference_type` aka ptrdiff_t (usually signed integer).

使用这种方法的强大之处在于它的多功能性。事实上,它也适用于"类c向量",std::array, std::list

您可以使用std::distance

 std::vector<Object> objects = /*..*/;
 const Object *p = /* object[i] */;
 std::ptrdiff_t index = std::distance(objects.data(), p);
 // Now index == i.

这里有很多好的答案。将它们结合在一起,这里有一个小的库套件,它允许通过指针或引用计算项的索引。

作为额外的奖励,调用方可以选择性地提供一个策略对象,如果元素不在容器中,则执行该策略对象。

#include <stdexcept>
#include <cassert>
#include <vector>

struct exception_policy
{
    [[noreturn]]
    std::size_t out_of_range() const
    {
        throw std::out_of_range("index_of_element");
    }
};
struct assertion_policy
{
    std::size_t out_of_range() const
    {
        assert(!"out of range");
        return _fallback.out_of_range();
    }
    exception_policy _fallback {};
};
struct zero_policy
{
    std::size_t out_of_range() const
    {
        return 0;
    }
};
template<class T, class A, class Policy = exception_policy>
std::size_t index_of_element(std::vector<T, A> const& vec,
                             typename std::vector<T, A>::const_pointer pitem,
                             Policy policy = Policy{})
{
    auto pbegin = vec.data();
    auto pend = pbegin + vec.size();
    if (pitem < pbegin or pitem >= pend)
    {
        return policy.out_of_range();
    }
    else
    {
        return std::distance(pbegin, pitem);
    }
}
template<class T, class A, class Policy = exception_policy>
std::size_t index_of_element(std::vector<T, A> const& vec,
                      typename std::vector<T, A>::const_reference item, Policy policy = Policy{})
{
    return index_of_element(vec, std::addressof(item), policy);
}
int main()
{
    std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8 };
    auto px = std::addressof(v[5]);
    auto& rx = *px;
    try {
        // use default policy of throwing out_of_range...
        auto i = index_of_element(v, rx);
        assert(i == 5);
    }
    catch(...)
    {
        assert(!"should not throw");
    }
    try {
        auto i = index_of_element(v, px);
        assert(i == 5);
    }
    catch(...)
    {
        assert(!"should not throw");
    }
    auto py = v.data() + 1000;  // out of bounds
    try {
        auto i = index_of_element(v, py);
        assert(!"should have thrown");
    }
    catch(std::out_of_range const& e)
    {
        // success
    }
    catch(...)
    {
        assert(!"should not throw this");
    }
    // specify a custom policy
    auto i = index_of_element(v, ry, zero_policy());
    assert(i == 0);    
}
int getIndex(Object* pObject) {return pObject - &(my_vewctor[0]);}

假设c++ 11至少:

您有一些class Myclass;(希望是一个相当小的,因为您有许多实例)。

你有一个变量std::vector<Myclass> bigvec;,它足够大,可以有大约50万个对象。

你有一个有效的指针Myclass* ptr;,它可以指向bigvec的对象内部。

您可以使用 在int ix;(或更好的size_t ix;)中获得bigvec中的索引。
if (ptr >= bigvec.data() && ptr < bigvec.data() + bigvec.size())
  ix = ptr - bigvec.data();

然而,要注意,你可以让复制Myclass(例如,通过赋值,通过值传递一些参数,等等…),然后指向这样一个副本的指针不会在bigvec