-2

我被要求优化 c++ 项目,我在类代码中遇到了这种“内存泄漏”情况(示例简化但主要问题很清楚):

std::list<T*> _list;
void func(){
    T* obj = some_func();
    if (!obj){
        obj = new T();
        _list.push_back(obj); // Here is a leak,we do not know when *obj will be removed from _list to call its destructor 
    }
    obj->some_field = some_value; 
}
/*_list will be used and managed somewhere else 
  and we do not know actually when, where and how.*/

那么如何优雅地解决这个问题呢?优雅地我的意思是没有定义我自己的容器。我需要使用一些智能指针吗?

更新。这不是 C++ 11。所以没有花哨有用的东西

4

5 回答 5

3

那么如何优雅地解决这个问题呢?

如果可能,存储对象,否则存储智能指针。通过哑指针进行内存管理会导致内存泄漏甚至更糟。

std::unique_ptr将是最好的智能指针 - 它匹配单个所有者(列表)的语义,具有将所有权转移进出的能力。然而,你说你被困在过去,所以最好的选择可能shared_ptr来自 TR1 或 Boost。

我需要使用一些智能指针吗?

假设您不能存储对象,这是迄今为止最简单的解决方案。另一种方法是仔细控制如何从列表中删除指针,确保您要么删除它们,要么以明确指定的方式转移所有权(并且新所有者正确履行其职责)。您实际上是在定义自己的容器适配器;尽管您可以使用现成的解决方案,例如 Boost 的指针容器。

于 2013-08-14T16:14:34.927 回答
0

如果没有 C++11,您可以使用std::auto_ptr<>. 这会将指针的所有权转移给一个所有者,因此如果_list是 type std::list<std::auto_ptr<T>>,则对象将在容器被销毁时被删除。

于 2013-08-14T17:30:27.773 回答
0

使用 some_func 的协议是什么?调用者是否应该拥有返回对象的所有权?如果是这样,它就会被泄露。您需要将 some_func 返回的 obj 推送到列表中,假设列表拥有对象的所有权。确实,在这里使用 unique_ptrs 将有助于使这一点更清楚。

于 2013-08-14T15:48:49.320 回答
0

假设您正在存储指向列表 ( std::list<T*> _list;) 的指针,也许这会有所帮助:

namespace RAII
{
    template<typename T>
    class AUTO_LIST_WITH_POINTER
    {
    public:
        AUTO_LIST_WITH_POINTER(){}
        ~AUTO_LIST_WITH_POINTER()
        {
            // if you compiler does not support lambdas, replace this with
            // a simple 'for' loop
            std::for_each( list_.begin(), list_.end(), []( T * & listItem )throw()
            {
                delete listItem;
            } );
        }

        const std::list<T*> & get()const
        {
            return list_;
        }

        std::list<T*> & get()
        {
            return list_;
        }

        std::list<T*> detach() // Warning: probably an expensive operation!!!!
        {
            std::list<T*> list( list_ );
            list_.clear();
            return list;
        }

    private:
        std::list<T*> list_;

        AUTO_LIST_WITH_POINTER( const AUTO_LIST_WITH_POINTER & );             // TODO: don't implement, or..?? the OP should know better
        AUTO_LIST_WITH_POINTER & operator=( const AUTO_LIST_WITH_POINTER & ); // TODO: don't implement, or..?? the OP should know better
    };
}
于 2013-08-14T15:59:08.157 回答
0

一种选择是使用 RAII,依赖于std::unique_ptr移动语义。例如:

std::list<std::unique_ptr<T>> list;
auto obj = some_func();
int some_value = 1;
if (!obj){
    std::unique_ptr<T> new_obj(new T());
    list.emplace_back(std::move(new_obj));
    obj = list.back().get();
}
obj->some_field = some_value;
于 2013-08-14T16:24:55.917 回答