代码之家  ›  专栏  ›  技术社区  ›  user1244932

不在临时上调用QString::运算符[]()

  •  8
  • user1244932  · 技术社区  · 7 年前

    我跑步 clazy 并获得有关此类代码的警告:

    QChar value() const
    {
        if (hide_content_)
            return '\0';
        else
            return text()[0];
    }
    

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

    警告是:

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

    但这意味着什么呢?是否可能是暂时的 QString 对象将被销毁 呼叫之前 operator[] ?

    1 回复  |  直到 7 年前
        1
  •  9
  •   Mike    7 年前

    是否可能在调用运算符[]之前销毁临时QString对象?

    不,警告不是关于不安全的操作。这里的行为完全被定义为临时行为 aren't destroyed 直到创建它们的完整表达式结束(即,直到 return 陈述)。

    总结: 警告与操作相关的性能问题有关。您可以使用 .at(0) 而不是 .operator[](0) . 如需解释,请继续阅读答案。


    首先,Qt的容器是 implicitly shared ; 这意味着,当您复制一个容器时,只有在对该容器执行写操作(又称写时复制)时,它的元素才会被实际复制。

    这意味着,每当容器检测到写入操作时,它都需要分离(执行深度复制),以便此隐式共享对用户保持透明。

    这包括容器对其中的项目发出非常量引用的情况(确切地说是非常量引用 operator[] ,因为它无法提前知道您(容器用户)将如何实际使用这些非常量引用。

    换句话说,假设我们有 QString str = "abc"; 当你写作时 QChar ch = str[0]; , QString 的非常量 操作员[] 调用,对于容器来说,这正是用户写入 str[0] = 'x'; . 这意味着每当对容器调用非常量操作时,该容器都需要分离。当用户实际上不打算更改容器中的任何内容时,用户的工作就是使用const函数。

    Clazy在这里试图检测用户在临时文件中获得非常量引用的情况(因为对即将被销毁的临时文件进行变异实际上没有意义)。


    有关更多信息:

    1. Uncovering 32 Qt best practices at compile time with clazy -请参见#8
    2. Effective Qt - Marc Mutz - Meeting C++ 2015