QString::utf16(): Is it UB or not?

QString::utf16(): Is it UB or not?

本文关键字:UB or it not Is utf16 QString      更新时间:2023-10-16

让我们看看以下源代码:

const ushort *QString::utf16() const
{
if (IS_RAW_DATA(d)) {
// ensure ''-termination for ::fromRawData strings
const_cast<QString*>(this)->reallocData(uint(d->size) + 1u);
}
return d->data();
}

reallocData((修改d指针类成员d,请参阅https://code.woboq.org/qt5/qtbase/src/corelib/tools/qstring.cpp.html#_ZN7QString11reallocDataEjb。如果QString对象是const呢?根据https://en.cppreference.com/w/cpp/language/const_cast用去掉constness来修改const对象是UB:

struct type {
int i;
type(): i(3) {}
void f(int v) const {
const_cast<type*>(this)->i = v; // OK as long as the type object isn't const
}
};
type t; // if this was const type t, then t.f(4) would be undefined behavior
t.f(4);

我们在这段特定的代码(QString::utf16(((中有UB吗?

如果调用此方法的QString对象是常量限定的,则这确实是一个UB:

QString const str{"whatever"};
str.utf16();

注意,这里的重要部分是对象是const限定的,而不是方法是const限制的。

如果(且仅当(有问题的对象最初是创建const:时,这是未定义的行为

QString const sc("whatever");
sc.utf16();                  // undefined behaviour!
QString s("whatever");
QString const& scr = s;
scr.utf16();                 // NOT undefined behaviour!

尽管如此,去掉constness是一个非常糟糕的想法,因为在函数中,你永远不知道有问题的对象是一个真正的const对象,还是只是一个指向最初创建的非const对象的指针/引用,所以UB总是存在的内在危险!

Best只是没有函数const:

const ushort* QString::utf16()
{
//...
}

在这种情况下,用户被迫创建一个非常数副本,即使原始对象实际上是非常数,但这总比冒UB的风险要好!