C++ qPrintable是否容易出现访问冲突?
qPrintable的定义:C++ qPrintable是否容易出现访问冲突?,c++,qt,C++,Qt,qPrintable的定义: # define qPrintable(string) QString(string).toLocal8Bit().constData() toLocal8Bit返回一个QByteArray。文件: 只要字节数组没有重新分配或销毁,指针就保持有效 toLocal8Bit()创建一个临时QByteArray,该数组在调用constData()后立即销毁。因此,constData返回的指针指向已释放的内存 我是不是遗漏了什么 补充意见: 各国的文件: 在使用qPri
# define qPrintable(string) QString(string).toLocal8Bit().constData()
toLocal8Bit返回一个QByteArray。文件:
只要字节数组没有重新分配或销毁,指针就保持有效
toLocal8Bit()创建一个临时QByteArray,该数组在调用constData()后立即销毁。因此,constData返回的指针指向已释放的内存
我是不是遗漏了什么
补充意见:
各国的文件:
在使用qPrintable()的语句之后,char指针将无效。这是因为QString::toLocal8Bit()返回的数组将超出范围
但这意味着什么?就我的理解而言,这与“指针从qPrintable返回的那一刻起就无效”相同
我为什么要问:
我见过代码失败,可以这样简化:
someFunction( stringA.toLatin1().constData(), stringB.toLatin1().constData())
在被调用的函数中,两个参数都是指向同一地址的指针。
qPrintable
宏应该用于调试目的:
qWarning("%s: %s", qPrintable(key), qPrintable(value));
或:
就我的理解而言,这与“指针从qPrintable返回的那一刻起就无效”相同
不。临时对象在其所属的完整表达结束时被销毁,除非通过引用常量延长其寿命。有关详细信息,请参阅。完整表达式一结束指针就无效
在像foo(obj1().method(),obj2().method())
这样的调用中,整个调用是一个完整表达式
因此,这将起作用:
#include <QtCore>
struct Test {
Test() { qDebug() << "created"; }
~Test() { qDebug() << "destroyed"; }
Test * fun() { return this; }
};
void f1(Test *, Test*) { qDebug() << "f1"; }
int main()
{
f1(Test().fun(), Test().fun());
}
我见过代码失败,可以这样简化:someFunction(stringA.toLatin1().constData(),stringB.toLatin1().constData())
。在被调用的函数中,两个参数都是指向同一地址的指针
“简化”确实很重要。一旦将每个qPrintable
从用作参数的完整函数调用表达式中拉出,就会出现问题:
int main()
{
auto a1 = Test().fun();
// here a1 dangles
auto a2 = Test().fun();
// here both a1 and a2 dangle
f1(a1, a2); // undefined behavior
}
输出:
created
created
f1
destroyed
destroyed
created
destroyed
created
destroyed
f1
qPrintable是否容易出现访问冲突
这取决于C++的语义有多清楚。考虑到它是一个过时的、不必要的构造,我只想说:不管是否倾向于未定义的行为,都没有理由使用它。如果需要将
QString
传递给需要const char*
的对象,请在适配器中明确说明
void foo(const char *); // we need to call this with a QString
void foo2(const char *, const char *);
inline void foo(const QString & arg1) { // now we can
auto a1 { arg1.toLocal8Bit() };
foo(a1.constData()); // a1's lifetime explicitly extends past the call
}
// or if you really like one-liners
inline void foo2(const QString & arg1, const QString & arg2) {
foo2(arg1.toLocal8Bit().constData(), arg2.toLocal8Bit().constData());
}
但这意味着什么?就我的理解而言,这与“指针从qPrintable返回的那一刻起就无效”相同
我也有同样的问题,但理解这一点的关键是要注意,qPrintable
是一个宏,而不是一个函数:
#如果可打印
#定义qPrintable(string)QtPrivate::asString(string).toLocal8Bit().constData()
#恩迪夫
(来自)
如果这是一个函数,你是对的。作为一个宏,没有回头路可谈。文件上写着“退货”,但这并不准确。因此,临时的范围是调用
qPrintable
的范围。QByteArray的生存期是否由标准保证?是的,是的。临时对象将一直存在,直到在其中创建它的完整表达式结束。
created
destroyed
created
destroyed
f1
void foo(const char *); // we need to call this with a QString
void foo2(const char *, const char *);
inline void foo(const QString & arg1) { // now we can
auto a1 { arg1.toLocal8Bit() };
foo(a1.constData()); // a1's lifetime explicitly extends past the call
}
// or if you really like one-liners
inline void foo2(const QString & arg1, const QString & arg2) {
foo2(arg1.toLocal8Bit().constData(), arg2.toLocal8Bit().constData());
}