我正在使用VC ++构建Qt应用程序,并且需要带有各种小部件的几种长格式。我试图动态分配这些小部件,以使添加新页面的过程更加简单。

为此,我将QStringList'key'和QVector 'vec'传递到保存该窗体的QDialog中。 key [i]的第一个字符保存窗口小部件类型,其余的保留标签。另一方面,每个vec [i]都需要保存用户更改的任何相应信息(来自动态创建的小部件)。

到目前为止,我已经在for循环中尝试了以下操作(每个循环都通过一个键):

char typeVal = key[i].toStdString()[0]; // widget type
key[i] = key[i].mid(1); // widget label

switch (typeVal)
{
    case 'e': // edit (lineedit)
    {
        QLineEdit *newEdit = new QLineEdit(page);
        connect(newEdit, &QLineEdit::textChanged, [&] {
            vec[vecIndex] = newEdit->text().toStdString(); });
        layout->addRow(key[i], newEdit);
        break;
    }
    // ...
}


但是,由于newEdit-> text(),这给了我一个“访问冲突读取位置”。这可能与我如何使用lambda函数槽有关,因为我对lambda声明了解不多。如果有此问题的解决方法,或者不必要地困扰整个过程,并且有更好的跟踪小部件数据的方法,我很想听听。

最佳答案

您报告的访问冲突问题可能有以下原因。

您将信号连接到以下lambda函数:

[&] { vec[vecIndex] = newEdit->text().toStdString(); }

其中[&]部分告诉编译器通过引用捕获所有变量,即,引用绑定到newEdit变量,该变量随后可在lambda函数体内使用。但是,这不是您在这种情况下想要的。实际上,对newEdit的引用已绑定到一个变量,该变量几乎在此绑定之后立即被销毁(即,在您的case语句作用域的末尾),因此请稍后尝试读取此变量(在插槽调用时)时间)导致尝试从已破坏的变量中读取内容,因此相应的内存位置可能只包含任何随机值,甚至根本无法读取。取消引用此类读取操作的结果会导致您报告分段错误。

这里需要的是newEdit指针的值(它是指向QLineEdit的指针,而不是对象本身),应保存以供lambda函数插槽以后使用。我想这同样适用于vecIndex,因为它看起来像您在问题中描述的某个循环变量,因此它会更改其值,并可能在循环完成后被破坏,但这取决于您应用程序的实际上下文。相反,vec变量可能需要按引用捕获,因为您要修改“全局”矢量,而不是为lambda函数创建的本地副本。

假设,我们来以下lambda函数的声明:

[&vec, vecIndex, newEdit] { vec[vecIndex] = newEdit->text().toStdString(); }

这表示了vec应该通过引用捕获的事实,而vecIndexnewEdit变量需要通过它们的值捕获。

希望这可以帮助。

07-24 14:05