user2138149
user2138149

Reputation: 17334

Get Element Position within std::vector

How do I get the position of an element inside a vector, where the elements are classes. Is there a way of doing this?

Example code:

class Object
{
  public:
    void Destroy()
    {
      // run some code to get remove self from vector
    }
}

In main.cpp:

std::vector<Object> objects;
objects.push_back( <some instances of Object> );
// Some more code pushing back some more stuff

int n = 20;
objects.at(n).Destroy(); // Assuming I pushed back 20 items or more

So I guess I want to be able to write a method or something which is a member of the class which will return the location of itself inside the vector... Is this possible?

EDIT:

Due to confusion, I should explain better.

void Destroy(std::vector<Object>& container){
  container.erase( ?...? );
}

The problem is, how can I find the number to do the erasing...? Apparently this isn't possible... I thought it might not be...

Upvotes: 0

Views: 2842

Answers (4)

Dominik Grabiec
Dominik Grabiec

Reputation: 10665

If you need to destroy the n'th item in a vector then the easiest way is to get an iterator from the beginning using std::begin() and call std::advance() to advance how ever many places you want, so something like:

std::vector<Object> objects;
const size_t n = 20;

auto erase_iter = std::advance(std::begin(objects), n);

objects.erase(erase_iter);

If you want to find the index of an item in a vector then use std::find to get the iterator and call std::distance from the beginning.

So something like:

Object object_to_find;
std::vector<Object> objects;

auto object_iter = std::find(std::begin(objects), std::end(objects), object_to_find);

const size_t n = std::distance(std::begin(objects), object_iter);

This does mean that you need to implement an equality operator for your object. Or you could try something like:

auto object_iter = std::find(std::begin(objects), std::end(objects), 
  [&object_to_find](const Object& object) -> bool { return &object_to_find == &object; });

Although for this to work the object_to_find needs to be the one from the actual list as it is just comparing addresses.

Upvotes: 0

Robᵩ
Robᵩ

Reputation: 168836

The object can erase itself thusly:

void Destroy(std::vector<Object>& container);
{
  container.erase(container.begin() + (this - &container[0]));
}

This will work as you expect, but it strikes me as exceptionally bad design. Members should not have knowledge of their containers. They should exist (from their own perspective) in an unidentifiable limbo. Creation and destruction should be left to their creator.

Upvotes: 1

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145429

Objects in a vector don't automatically know where they are in the vector.

You could supply each object with that information, but much easier: remove the object from the vector. Its destructor is then run automatically.

Then the objects can be used also in other containers.


Example:

#include <algorithm>
#include <iostream>
#include <vector>

class object_t
{
private:
    int     id_;
public:
    int id() const { return id_; }

    ~object_t() {}
    explicit object_t( int const id ): id_( id ) {}
};

int main()
{
    using namespace std;
    vector<object_t> objects;

    for( int i = 0;  i <= 33;  ++i )
    {
        objects.emplace_back( i );
    }

    int const n = 20;
    objects.erase( objects.begin() + n );

    for( auto const& o : objects )
    {
        cout << o.id() << ' ';
    }
    cout << endl;
}

Upvotes: 0

eladidan
eladidan

Reputation: 2644

You can use std::find to find elements in vector (providing you implement a comparison operator (==) for Object. However, 2 big concerns:

  1. If you need to find elements in a container then you will ger much better performance with using an ordered container such as std::map or std::set (find operations in O(log(N)) vs O(N)
  2. Object should not be the one responsible of removing itself from the container. Object shouldn't know or be concerned with where it is, as that breaks encapsulation. Instead, the owner of the container should concern itself ith such tasks.

Upvotes: 1

Related Questions