You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遍历QButtonGroup::buttons导致程序崩溃的原因解析

QButtonGroup遍历崩溃问题分析

问题代码

初始化代码:

auto box1=new QCheckBox;
box1->setText("choice1");
auto box2=new QCheckBox;
box2->setText("choice2");
QPushButton* button=new QPushButton;
connect(button,&QPushButton::clicked,this,&Widget::onClicked);
auto group=new QButtonGroup;
group->setExclusive(false);
group->addButton(box1);
group->addButton(box2);

槽函数代码:

void Widget::onClicked()
{
    // 崩溃的写法
    std::for_each(group->buttons().begin(),group->buttons().end(),[](QAbstractButton* button){
            button->setChecked(!button->isChecked());
    });
    /*
    // 正常运行的写法
    QList<QAbstractButton *> buttons=group->buttons();
    std::for_each(buttons.begin(),buttons.end(),[](QAbstractButton* button){
        button->setChecked(!button->isChecked());
    });
    */
}

崩溃原因解析

QButtonGroup的buttons()方法是值返回,也就是说每次调用该方法,都会创建并返回一个全新的QList<QAbstractButton*>临时对象。

在崩溃的写法里:

  • group->buttons().begin()是从第一个临时QList对象中获取起始迭代器
  • group->buttons().end()则是从第二个完全独立的临时QList对象中获取结束迭代器

这两个迭代器属于不同的容器实例,用它们组成的范围进行遍历是C++标准中定义的未定义行为。同时临时对象会在当前表达式结束后立即销毁,迭代器会变成悬空迭代器。这种情况下遍历会出现范围错误(比如你看到的循环执行三次),最终访问到非法内存地址导致程序崩溃。

而正常运行的写法中,先将buttons()的返回值赋值给局部变量buttons,此时begin()和end()都来自同一个QList实例,迭代器匹配且容器对象在遍历期间始终有效,因此遍历过程安全且正确。

内容的提问来源于stack exchange,提问作者air

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:17:20