将Qt对象与std :: shared_ptr一起使用

sap*_*sap 2 c++ qt shared-ptr

我正在尝试将一个小的实用程序应用程序更新为更现代的C++方式,但是我在使用std :: shared_ptr的一些Qt对象时遇到了问题,特别是那些接收其他QWidget作为构造函数参数的那些.

例如:

private:
    std::shared_ptr<QWidget> centralwidget;
    std::shared_ptr<QVBoxLayout> verticalLayout;

public:
    void setupUi(QMainWindow *MainWindow) // this pointer is a .get() from a shared_ptr
    {
        centralwidget = std::make_shared<QWidget>(new QWidget(MainWindow)); // compiles fine
        verticalLayout = std::make_shared<QVBoxLayout>(new QVBoxLayout(centralwidget.get())); // does not compile
    }
Run Code Online (Sandbox Code Playgroud)

编译错误是:

错误1错误C2664:'QVBoxLayout :: QVBoxLayout(QWidget*)':无法将参数1从'QVBoxLayout*'转换为'QWidget*'e:\ microsoft visual studio 11.0\vc\include\memory 855

我似乎无法理解这个错误,我没有转换任何东西,我只是想创建一个QVBoxLayout对象并传递一个QWidget作为其父(就像我会用原始指针).

Fré*_*oni 9

一般来说,我尽量避免使用shared_ptr用于Qt GUI对象,因为Qt已经提供了自己的内存管理机制.每个QObject可能都有一个父对象,当这个父对象死亡时,他会删除它的所有子对象.这里不需要shared_pointer,也没有给你任何附加值:你可以完美地使用原始指针而不会产生内存泄漏.

一般来说,如果QObject的父级在删除最后一个shared_ptr实例之前就死了,那么你很快就会遇到麻烦,因为当最后一个shared_ptr被销毁时,该对象将被第二次删除.这不是这里的情况,但要小心:)

  • 我再怎么强调这个答案的第二段都不为过。混合`std::shared_ptr&lt;QObject&gt;` 和Qt-ish 父子所有权机制是*真正*危险的!它会导致您准确描述的崩溃。我想警告大家不要在 `std::shared_ptr` 中保存从 `QObjects` 派生的对象。只有当您确定 `QObject` 没有并且永远不会有父对象或者共享指针在父对象之前被销毁时,这才是安全的,但是很难强制执行,尤其是在大型代码库中。对于总是有父母的`QWidgets` 是不可能的。 (2认同)

sla*_*ppy 5

std::make_shared传递的参数将传递到您要实例化的类的构造函数。因此,基本上您在做什么等同于:

new QVBoxLayout(new QVBoxLayout(centralwidget.get()))
Run Code Online (Sandbox Code Playgroud)

我认为您正在尝试做的是:

centralwidget = std::make_shared<QWidget>(MainWindow);
verticalLayout = std::make_shared<QVBoxLayout>(centralwidget.get());
Run Code Online (Sandbox Code Playgroud)

查看的文档std::make_shared(例如在此处)。该功能的全部目的是在内存中的对象实例附近分配引用计数,因此您必须让它为您分配内存。