c++ 遍历QButtonGroup::buttons导致崩溃

odopli94  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(250)

这是我的符号定义:

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);

个字符
buttons()调用将返回一个QList<QAbstractButton *>
我尝试使用onClicked插槽来遍历列表并做一些事情。
如果我添加了未注解的代码段,程序会崩溃。我调试了它,发现它循环了三次,但实际上只添加了两个元素,第三次循环会使程序崩溃。
如果我删除注解掉的代码,它就可以工作了。
我想知道为什么第一种编写方式,即没有注解掉的代码会导致错误。

falq053o

falq053o1#

正如我在评论中所解释的(我自己没有检查过,但@musicamente证实了),std::for_each(group->buttons().begin(), group->buttons().end(), [...])创建了两个单独的列表(通过复制构造),其中的end()迭代器是不同的;重要的是,你不能从前者的begin()迭代器到达后者的end()迭代器,这会导致std::for_each一直循环到末尾。
这个问题不会发生在基于范围的循环中(这更容易阅读到顶部)。当我在这里的时候,我将使用toggle方法来切换复选框的checkstate:

void Widget::onClicked()
{
    for (auto checkbox: group->buttons())
        button->toggle();
}

字符串
在一个单独的说明中,除非你有一个特定的原因来做你在你的问题中提出的方式,例如@musicamente下面的评论(但即使这样,我宁愿在运行时创建一个新的复选框时创建一个连接+当对象被删除时断开连接是自动的),将按钮连接到许多复选框的正确方法是:

[...]
QPushButton* button=new QPushButton;
auto group=new QButtonGroup;
group->setExclusive(false);
group->addButton(box1);
group->addButton(box2);
for (auto checkbox : group->buttons())
    QObject::connect(button, &QAbstractButton::clicked, checkbox, &QAbstractButton::toggle);


这节省了声明void Widget::onClicked()
根据Widget类的其他部分,它甚至可以在没有group的情况下工作,以这种方式:

[...]
QPushButton* button=new QPushButton;
for (auto checkbox : findChildren<QCheckBox>(QString()))
    QObject::connect(button, &QAbstractButton::clicked, checkbox, &QAbstractButton::toggle);

相关问题