C++ qPrintable是否容易出现访问冲突?

C++ qPrintable是否容易出现访问冲突?,c++,qt,C++,Qt,qPrintable的定义: # define qPrintable(string) QString(string).toLocal8Bit().constData() toLocal8Bit返回一个QByteArray。文件: 只要字节数组没有重新分配或销毁,指针就保持有效 toLocal8Bit()创建一个临时QByteArray,该数组在调用constData()后立即销毁。因此,constData返回的指针指向已释放的内存 我是不是遗漏了什么 补充意见: 各国的文件: 在使用qPri

qPrintable的定义:

#  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());
}