【问题标题】:QList and shared_ptrQList 和 shared_ptr
【发布时间】:2010-10-21 19:57:01
【问题描述】:

你怎么看?这是正确的还是存在内存泄漏?

来源:

#include <QList.h>
#include <boost/shared_ptr.hpp>
#include <iostream>

class A {
private:
    int m_data;
public:
    A(int value=0) { m_data = value; }
    ~A() { std::cout << "destroying A(" << m_data << ")" << std::endl; }
    operator int() const { return m_data; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    QList<boost::shared_ptr<A> > list;
    list.append(boost::shared_ptr<A>(new A(6)));
    std::cout << int(*(list.at(0))) << std::endl;
    return 0;
}

输出:

6
destroying A(6)

【问题讨论】:

  • 作为旁注:不要使用QList&lt;T&gt; where sizeof(T) &gt; sizeof(void*)(和sizeof( shared_ptr&lt;T&gt; ) == 2*sizof(void*),通常),因为在这种情况下QList将复制-new元素到列表中(而不是按价值持有)。请改用QVectorstd::vector

标签: c++ qt boost qlist


【解决方案1】:

这似乎是正确的。 Boost 的 shared_ptr 是一个引用计数指针。如果对象之间没有循环引用,引用计数能够回收内存。在您的情况下, A 类的对象不引用任何其他对象。因此,您可以放心使用 shared_ptr。此外,所有权语义允许在 STL(和 Qt)容器中使用 shared_ptrs。

【讨论】:

    【解决方案2】:

    这段代码看起来很好。

    如果您正在寻求建议,也许您可​​以提供有关将 shared_ptr 与 QList 一起使用的目的的更多信息,可能有一种“Qt”方式可以做到这一点,而无需像 shared_ptr 这样的大手笔。

    【讨论】:

    【解决方案3】:

    如果不知道为什么首先存在A 对象的shared_ptrs 列表,就很难提出任何建议。

    看看ownership semantics 的智能指针。也许对你有帮助。

    其他一些可以改进的地方:

    1. 在 ctor 中使用初始化列表,例如:

    class A {
     private:
       int m_data;
     public:
        A(int value=0) : m_data (value) {}
     // ....
    

    2. int _tmain(int argc, _TCHAR* argv[]) 不是标准签名;

    使用

    int main(int argc, char* argv[])
    

    或者只是:

    int main()
    

    【讨论】:

    • 我不确定你的第一点是什么意思。我应该在哪里使用初始化列表? _tmain 是使用 Visual Studio 向导时的默认设置,但感谢您的提示!
    • _tmain(int argc, _TCHAR* argv[]) 是 VC++ 上的有效签名 :)。它是一个主要方法,可以采用多字节或 unicode 参数,具体取决于 VS 中的开关。还有一个 int wmain(int argc, wchar_t *argv[])。
    • 一个实现可以提供N个不同的main签名。语言标准只定义了两个(我在上面提到过)。
    • 是的,这是真的。但正如我所说,它在 VC++ 上完全有效。
    【解决方案4】:

    如果你不使用智能指针,你必须自己删除列表元素。

    来源:

    #include <QList.h>
    #include <boost/shared_ptr.hpp>
    #include <iostream>
    
    class A {
    private:
        int m_data;
    public:
        A(int value=0) { m_data = value; }
        ~A() { std::cout << "destroying A(" << m_data << ")" << std::endl; }
        operator int() const { return m_data; }
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        QList<A *> list;
        list.append(new A(6));
        std::cout << int(*(list.at(0))) << std::endl;
        return 0;
    }
    

    输出:

    6
    

    不好。

    【讨论】:

    • 那么只要去掉“new”操作符,当QList是时A对象就会被解构。
    • @ParkerCoates 那么它不会是一个指针列表,并且对象将在追加时被复制。对于最初构造的对象,析构函数将被调用一次,而当列表被销毁时,将再次为副本调用一次。
    猜你喜欢
    • 2018-03-31
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 2013-06-12
    • 2013-04-16
    • 1970-01-01
    • 2011-04-19
    • 2012-09-01
    相关资源
    最近更新 更多