【问题标题】:smart pointers instead of pointers智能指针代替指针
【发布时间】:2017-04-29 09:35:33
【问题描述】:

对不起我的英语。我有相同的代码:

auto windowsStack = m_windowManger->windowsStack();

auto ListModel = new QStandardItemModel();

while(!windowsStack.empty())
{
    auto window = windowsStack.top();
    auto title = QString::fromUtf8(window->title().c_str());

    auto Items = new QStandardItem(title);
    ListModel->appendRow(Items);

    windowsStack.pop();
}

ui->listView->setModel(ListModel);

一切正常,我的任务是替换指向智能指针的指针。我做了不止一次,我的决定:

auto windowsStack = m_windowManger->windowsStack();

auto ListModel = std::shared_ptr<QStandardItemModel>();

while(!windowsStack.empty())
{
    auto window = std::shared_ptr<Window>(windowsStack.top());
    auto title = QString::fromUtf8(window->title().c_str());

    auto Items = std::shared_ptr<QStandardItem>(new QStandardItem(title));
    ListModel->appendRow(Items.get());

    windowsStack.pop();
}

ui->listView->setModel(ListModel.get());

但最后,我得到消息:程序意外结束。在提示符处输入:

ListModel->appendRow(Items.get());

新版本:

auto ListModel = std::make_shared<QStandardItemModel>();
while(!windowsStack.empty())
{
    auto window = windowsStack.top();
    windowsStack.pop();
    auto title = QString::fromUtf8(window->title().c_str());
    ListModel->appendRow(new QStandardItem(title));
}

ui->listView->setModel(ListModel.get());

【问题讨论】:

    标签: c++ c++11 pointers smart-pointers


    【解决方案1】:

    这里有几个问题。第一个是在 cmets 和 Edgar Rokyans 的回答中指出的,您将 ListModel 创建为空的 shared_ptr,首先通过使用 make_shared 分配一个项目来解决这个问题

    auto ListModel = std::make_shared<QStandardItemModel>();
    

    更险恶的错误是您在循环中创建元素,然后将非拥有指针传递给ListModel,当Items 的析构函数运行时,这些指针在循环结束时变得无效。 QStandardItemModeldefined to delete the items it has,因此您不应该在传递项目之前使用 shared_ptr 分配项目。而只需分配并调用 appendRow。此外,您将从windowsStack 获得的内容包装在shared_ptr 中,但windowsStack 似乎是拥有指针堆栈的副本,​​所以这是一件奇怪的事情。我不能确定,但​​看起来你实际上想要在这里使用原始指针,或者让windowsStack 成为shared_ptr 的堆栈。我不能确定,因为我不知道 windowsStack() 返回什么 - 它可能是拥有原始指针的堆栈,指向调用者应该删除的动态分配的内存。

    while(!windowsStack.empty()) {
        auto window = windowsStack.top();
        windowsStack.pop();
        auto title = QString::fromUtf8(window->title().c_str());
        ListModel->appendRow(new QStandardItem(title));
    }
    

    【讨论】:

    • 谢谢,有没有写。错误消失了,但 QListView 没有添加任何内容。虽然它适用于裸指针。
    • 你仍然需要最后一行 ui-&gt;listView-&gt;setModel(ListModel.get()); 我只是重写循环,这是有缺陷的。
    • 我没有删除最后一行,就是这样,我在上面的问题中添加了一个新版本。所以没有添加到 qlistview 中。
    • 我想我可能误解了你的英语,извините,但如果我不是:当ListModel 超出范围时,它会破坏它所指向的内容。如果ui-&gt;listView 的寿命比ListModel 长,它将是一个悬空指针。如果你在 linux 上运行,你应该通过 valgrind 运行它
    【解决方案2】:
    auto ListModel = std::shared_ptr<QStandardItemModel>();
    

    在这一行创建一个空的共享指针ListModel

    尝试替换为:

    auto ListModel = std::shared_ptr<QStandardItemModel>(new QStandardItemModel());
    

    正如 Ryan 指出的,最好使用std::make_shared,这有助于减少代码量并避免冗余内存分配:

    auto ListModel = std::make_shared<QStandardItemModel>();
    

    注意:

    我刚刚描述了一个错误。似乎您的代码中还有其他问题。查看 Ryan 的回答了解更多详情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      • 2015-01-24
      • 1970-01-01
      • 2019-01-20
      • 2021-11-28
      相关资源
      最近更新 更多