QList and shared_ptr

5
你认为呢?这是否正确或存在内存泄漏?
来源:
#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)

2
作为附注:在sizeof(T) > sizeof(void*)(以及sizeof(shared_ptr<T>) == 2*sizeof(void*),通常情况下),请不要使用QList<T>,因为在这种情况下,QList会将元素拷贝-new到列表中(而不是按值保存)。请改用QVectorstd::vector - Marc Mutz - mmutz
4个回答

1

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

看一下智能指针的所有权语义。也许对你有帮助。

其他可以改进的事情:

1. 在构造函数中使用初始化列表,例如:

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向导时的默认选项,但感谢您的提示! - WolfgangP
1
_tmain(int argc, _TCHAR* argv[]) 是VC++上的有效签名 :).这是一个主方法,根据VS中的开关,可以接受多字节或Unicode参数。还有一个 int wmain(int argc, wchar_t *argv[])。 - Skurmedel
一个实现可以提供 N 种不同的 main 签名。语言标准只定义了两种(如上所述)。 - dirkgently
是的,那是真的。但正如我所说,它在VC++上是完全有效的。 - Skurmedel

1

如果您没有使用智能指针,那么您必须自己删除列表元素。

来源:

#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”运算符,A对象将在QList销毁时被析构。 - Parker Coates
@ParkerCoates 那么它将不是一个指针列表,对象将在追加时被复制。析构函数将被调用两次,一次是为了最初构造的对象,另一次是为了在列表销毁时复制的对象。 - syockit

1

这段代码看起来完全没问题。

如果你正在寻求建议,也许你可以提供更多关于使用shared_ptr和QList的目的的信息,可能有一种“Qt”的方法可以做到这一点,而不必使用像shared_ptr这样的大招。


我在尝试使用QList<A *>,在这样做时你必须自己处理列表元素。显然这很烦人。我还没有找到一种Qt的智能指针用法。 - WolfgangP
1
这并不完全正确。你可以使用Qt的对象所有权树形布局,将QList作为插入到其中的每个对象的所有者进行传递。当使用Qt时,这是一种非常有用的技术。在这里阅读更多信息:http://doc.trolltech.com/4.5/objecttrees.html - Idan K
@daniel 这里不是一个选项,因为父对象和子对象必须是QObject的子类才能工作。QList不是QObject,所以即使A继承自QObject也不行。 - Parker Coates
真的,完全忘记了 QList 不是 QObject!不过这还是有用的,取决于使用 QList 的上下文。 - Idan K

1

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接