不要临时调用QString :: operator []()

use*_*932 6 c++ qt

我对我的代码运行clazy并得到有关此类代码的警告:

QChar value() const
{
    if (hide_content_)
        return '\0';
    else
        return text()[0];
}
Run Code Online (Sandbox Code Playgroud)

哪里text()有这样的签名QString text() const;

警告是:

warning: Don't call QString::operator[]() on temporary
      [-Wclazy-detaching-temporary]
            return text()[0];
                   ^
Run Code Online (Sandbox Code Playgroud)

但是这是什么意思?是否可能QString在调用之前销毁临时对象operator[]

Mik*_*ike 5

在调用operator []之前,是否可能会销毁临时QString对象?

不,警告不是一个不安全的操作.这里的行为是完全定义的,因为临时数据在创建它们的完整表达式结束之前不会被销毁(即直到return你的情况下语句的结尾).

摘要:警告是关于与操作相关的性能问题.您可以使用.at(0)而不是使用它来修复它.operator[](0).有关解释,请继续阅读答案.


首先,Qt的容器是隐含共享的 ; 这意味着当您复制容器时,在对容器执行写入操作(也称为copy-on-write)之前,其元素实际上不会被复制.

这意味着只要容器检测到写入操作,就需要分离(执行深层复制),以便这种隐式共享对用户保持透明.

这包括容器向其中的项目发出非const引用的情况(正是非const operator[]正在做的事情),因为它无法事先知道您(容器用户)将如何实际使用这些非const引用.

换句话说,假设我们有一个QString str = "abc";写入的时候QChar ch = str[0];,QString非const operator[]被调用,而对于容器,这正是用户写入时所知道的str[0] = 'x';.这意味着只要在其上调用非const操作,容器就需要分离.当用户不想真正改变容器中的任何东西时,使用const函数是用户的工作.

Clazy在这里试图检测用户在临时内部获取非const引用的情况(因为改变一个即将被销毁的临时变量没有意义).


欲获得更多信息:

  1. 在编译时使用clazy发现32个Qt最佳实践 - 请参阅#8
  2. 有效的Qt - Marc Mutz - 迎接C++ 2015