我可以直接从C ++中的向量元素指针获取索引吗?

时间:2016-08-25 09:57:37

标签: c++ pointers vector

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

有没有快速的方法来使用指针获取向量中的对象索引?

6 个答案:

答案 0 :(得分:2)

由于向量按顺序组织,您可以通过从指向相关元素的指针中减去指向初始元素的指针来获取索引:

std::vector<MyObject> vect;
MyObject *ptrX = ... // Pointer to element in question
ptrdiff_t index = ptrX - &vect[0];

答案 1 :(得分:2)

在这种情况下,

Iterator header应该很有用。

我们假设你有类似的东西:

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

Vector big_vector;

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

Iterator p_obj = get_Theobj(big_vector);

可以使用distance轻松获取索引:

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

使用这种方法的强大之处在于多功能性。实际上,它也适用于&#34;类C矢量&#34;,std::arraystd::list

答案 2 :(得分:1)

您可以使用std::distance

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

答案 3 :(得分:0)

int getIndex(Object* pObject) {return pObject - &(my_vewctor[0]);}

答案 4 :(得分:0)

至少假设C ++ 11:

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

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

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

您可以使用

bigvecint ix;(或更好size_t ix;)获取其索引
if (ptr >= bigvec.data() && ptr < bigvec.data() + bigvec.size())
  ix = ptr - bigvec.data();

但是,请注意,您可以创建Myclass副本(例如,通过赋值,通过值传递一些参数等等),然后指向这样的指针副本不在bigvec

答案 5 :(得分:0)

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

作为额外的奖励,如果元素不在容器中,调用者可以选择提供策略对象。

#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);    
}