获取std::vector中的元素位置

Get Element Position within std::vector

本文关键字:元素 位置 vector std 获取      更新时间:2023-10-16

如何获取向量中元素的位置,其中元素是类。有办法做到这一点吗?

示例代码:

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

在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

所以我想我想能够写一个方法或东西,它是类的一个成员,它将返回向量中它自己的位置。。。这可能吗?

编辑:

由于困惑,我应该解释得更好。

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

问题是,我如何找到要擦除的号码。。。?显然这是不可能的。。。我以为可能不是…

您可以使用std::find查找vector中的元素(前提是为Object实现比较运算符(==))。然而,两大问题:

  1. 如果您需要在容器中查找元素,那么使用有序容器(如std::mapstd::set)将获得更好的性能(在O(log(N))中查找操作与在O(N)中查找操作
  2. Object不应负责将其自身从容器中移除。Object不应该知道或关心它在哪里,因为这会破坏封装。相反,容器的所有者应该关心这样的任务

对象可以这样擦除自己:

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

这将如你所期望的那样工作,但我觉得它的设计异常糟糕。成员不应该知道他们的集装箱。他们应该(从他们自己的角度)存在于一个无法识别的边缘地带。创造和毁灭应该留给创造者。

向量中的对象不会自动知道它们在向量中的位置。

您可以为每个对象提供这些信息,但要简单得多:从向量中删除对象。然后它的析构函数会自动运行。

然后这些对象也可以在其他容器中使用。


示例:

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

如果您需要销毁向量中的第n个项,那么最简单的方法是从一开始就使用std::begin()获取迭代器,并调用std::advance()来提前您想要的位置,例如:

std::vector<Object> objects;
const size_t n = 20;
auto erase_iter = std::advance(std::begin(objects), n);
objects.erase(erase_iter);

如果要在向量中查找项的索引,请使用std::find获取迭代器并从头调用std::distance

所以类似于:

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

这确实意味着您需要为对象实现一个相等运算符。或者你可以试试类似的东西:

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

尽管要做到这一点,object_to_find需要是实际列表中的对象,因为它只是在比较地址。