我在初始化列表中使用QString时遇到了访问冲突,我不明白。
这是一个重现问题的最小例子。
// file ClassA.h
#pragma once
#include <QString>
struct Parameter
{
QString stringPar;
};
class ClassA
{
QString m_string1;
public:
void function(Parameter pars);
};
ClassA的实施......
// file ClassA.cpp
#include "ClassA.h"
void ClassA::function(Parameter pars)
{
m_string1 = pars.stringPar; // last line called in my code when the crash happens
}
和main.cpp
// file main.cpp
#include "ClassA.h"
int main()
{
ClassA classA;
classA.function({ QString("jkjsdghdkjhgdjufgskhdbfgskzh") });
// when using this code the problem does not occur
//Parameter par = { QString("jkjsdghdkjhgdjufgskhdbfgskzh") };
//classA.function(par);
return 0;
}
违规时的调用堆栈:
Qt5Cored.dll!QGenericAtomicOps<QAtomicOpsBySize<4> >::load<long>(const long & _q_value) Line 96
Qt5Cored.dll!QBasicAtomicInteger<int>::load() Line 142
Qt5Cored.dll!QtPrivate::RefCount::ref() Line 57
Qt5Cored.dll!QString::operator=(const QString & other) Line 1355
EducationalCode.exe!ClassA::function(Parameter pars) Line 6
EducationalCode.exe!main() Line 8
ClassA :: function()中的复制赋值似乎出了问题,但我不确定它是什么。 当我将功能的签名更改为
时function(const Parameter& pars);
它也不会崩溃。
你有什么想法吗?
答案 0 :(得分:0)
您应该添加一个复制构造函数:
struct Parameter
{
QString stringPar;
Parameter& Parameter(const Parameter& rhs)
{
if((void*)this == (void*)&rhs)
{
return *this;
}
this->stringPar = rhs.stringPar;
return *this;
}
};
当您调用ClassA :: function()时,会创建一个临时参数实例,因为C ++按值传递参数; 像这样:
void ClassA::function(Parameter pars = QString("jkjsdghdkjhgdjufgskhdbfgskzh"))
{
m_string1 = pars.stringPar; // last line called in my code when the crash happens
}
如果您不编写复制构造函数,编译器将合成一个默认的复制构造函数,如下所示:
Parameter& Parameter(const Parameter& rhs)
{
memcpy(this, &rhs, sizeof(Parameter));
return *this;
}
我猜QString有指针成员,假设它的名字是ptr。 然后是pars.stringPar.ptr和QString(“jkjsdghdkjhgdjufgskhdbfgskzh”)。stringPar.ptr将指向相同的内存地址。
这样调用函数:
classA.function({ QString("jkjsdghdkjhgdjufgskhdbfgskzh") });
{QString(“jkjsdghdkjhgdjufgskhdbfgskzh”)}对象在classA.function()返回之前销毁, 然后由{QString(“jkjsdghdkjhgdjufgskhdbfgskzh”)}指向的内存.stringPar.ptr被释放, 和pars.stringPar.ptr指向无效的内存。
// when using this code the problem does not occur
//Parameter par1 = { QString("jkjsdghdkjhgdjufgskhdbfgskzh") };
//classA.function(par1)
//par1 destroy when main() function return, thus classA.function() does not crash.
参见&lt;&lt;有效的C ++&gt;&gt; 第11项:为具有动态分配内存的类声明复制构造函数和赋值运算符。 有效的C ++,2E http://debian.fmi.uni-sofia.bg/~mrpaff/Effective%20C++/EC/EI11_FR.HTM