让我们看下面的源代码:
const ushort *QString::utf16() const
{
if (IS_RAW_DATA(d)) {
// ensure '\0'-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怎么办?根据{{3}},通过抛弃常量来修改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吗?
答案 0 :(得分:5)
如果在其上调用此方法的QString
对象是const限定的,则这确实是UB:
QString const str{"whatever"};
str.utf16();
请注意,这里重要的一点是对象是const限定的,而不是方法是const限定的。
答案 1 :(得分:0)
当(且仅当)所涉及的对象最初是创建的const
时,这是未定义的行为:
QString const sc("whatever");
sc.utf16(); // undefined behaviour!
QString s("whatever");
QString const& scr = s;
scr.utf16(); // NOT undefined behaviour!
仍然,抛弃constness是一个非常糟糕的想法,因为在函数内部,您永远不知道所讨论的对象是真正的const对象还是仅是对象的指针/引用最初创建的是非常量,因此UB总是存在 内在危险!
最好的就是没有const函数:
const ushort* QString::utf16()
{
//...
}
视情况而定,然后即使原始对象实际上是 ,用户也不得不创建非常量副本,但这总是比冒险使用UB更好!
>