删除后指向列表元素的指针

时间:2015-02-20 15:23:40

标签: c++ pointers memory

我有一个存储对象的列表。

list<MyObject> l;

我还有一个方法返回指向其中一个对象的指针(如果存在),否则返回nullp。

MyObject* get(int x) {
    for (std::list<MyObject>::iterator it = l.begin(); it != l.end(); ++it) {
        if (it->X == x) {
            return &(*it);
        }
    }
    return nullptr;
}

如果我得到()一个指向元素的指针,当我使用它时,它会从另一个线程中删除,指针变为无效,并且会发生奇怪的事情:)

我想知道的是,如果有一种方法可以在get()中返回一些特殊类型的指针,那么如果我在一个元素上调用erase并且该元素仍然被引用,那么它的内存将不会被释放直到指向它的指针超出范围。

我考虑使用引用,但是我需要在get上返回nullptr的可能性,所以我可以从调用者检查返回是否确实是一个有效的对象。

有人可以建议更好的方法来避免这些内存问题吗?

2 个答案:

答案 0 :(得分:2)

根据建议您应该使用一些smart_pointer来管理共享所有权。

一些建议:

  • 始终使用默认值std::vector
  • 如果可以使用C ++ 11使用标准shared_ptr进行共享所有权,如果没有,请使用boost版本。
  • 尽可能多地使用algorithm标题(在这种情况下find_if是正确的标题)。

您还应该尝试使用该算法搜索特定元素。以下是一些示例代码:

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

struct MyObject {
    int X;
    MyObject(int x_value) : X(x_value) {}
};

using element_t = std::shared_ptr<MyObject>;

std::vector<element_t> l{
    std::make_shared<MyObject>(3), std::make_shared<MyObject>(4),
    std::make_shared<MyObject>(5), std::make_shared<MyObject>(6),
    std::make_shared<MyObject>(7), std::make_shared<MyObject>(8)};

element_t get(int x) {
    auto it = std::find_if(std::begin(l), std::end(l),
                           [x](const element_t& elem) { return elem->X == x; });

    element_t found;
    if (it != std::end(l)) {
        found = *it;
    }
    return found;
}

int main() {
    auto f1 = get(6);
    if (f1) {
        std::cout << "encontrado " << f1->X << std::endl;
    } else {
        std::cout << "6 no se encontro" << std::endl;
    }

    auto f2 = get(10);
    if (f2) {
        std::cout << "encontrado " << f2->X << std::endl;
    } else {
        std::cout << "10 no se encontro" << std::endl;
    }

    return 0;
}

答案 1 :(得分:1)

在使用智能指针之前,您可能需要确保能够说明为什么您不能(或不想)设计一个系统,在该系统中您的对象在给定时间只有一个所有者。

智能指针将避免无效的数据访问,但它们有各种或多或少的隐藏问题

  • 它们需要额外的内存,强迫您使用它们以及它们在任何地方的移动语义,并且可能很容易变得棘手,例如:如果您保留循环引用或希望对象返回一个智能指针,
  • std::容器基本上就像用任何类型的指针填充它们一样无用(指针向量不是对象的向量),
  • 您无法控制取消分配的位置,因此您可能会通过任何引用它们的任务删除您的对象,这可能是时间要求严重的,
  • 不清楚谁拥有的东西往往不是灾难的秘诀。

例如,让一个线程决定删除对象,而另一个线程从同一存储中抓取一些而没有任何同步是非常危险的。有点好像一个线程认为该对象无效而另一个认为它有效 不会让我觉得这是最强大的设计,但你肯定有自己的理由。

我认为您可以先使用unique_ptr来查看是否符合您的需求,而不是立即跳转到shared_ptr