9

I want to efficiently compare a QString and a std::string for (in)equality. Which is the best way to do it, possibly without creating intermediate objects?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Ber
  • 40,356
  • 16
  • 72
  • 88
  • 5
    QString holds unicode, std::string can be anything, so there's no straight way defining "equality" here without assumptions about the content of the std::string. – Frank Osterfeld Aug 14 '13 at 12:42

2 Answers2

5

QString::fromStdString() and QString::toStdString() comes to mind, but they create temporary copy of the string, so afaik, if you don't want to have temporary objects, you will have to write this function yourself (though what is more efficient is a question).

Example:

    QString string="string";
    std::string stdstring="string";
    qDebug()<< (string.toStdString()==stdstring); // true


    QString string="string";
    std::string stdstring="std string";
    qDebug()<< (str==QString::fromStdString(stdstring)); // false

By the way in qt5, QString::toStdString() now uses QString::toUtf8() to perform the conversion, so the Unicode properties of the string will not be lost (qt-project.org/doc/qt-5.0/qtcore/qstring.html#toStdString

Shf
  • 3,463
  • 2
  • 26
  • 42
  • 2
    The first option, (string.toStdString()==stdstring), caused a leak memory on Windows on ARM (not a desktop or Linux issue). The second option, (str==QString::fromStdString(stdstring)), works fine. – pixelgrease Jan 13 '17 at 02:10
0

It can be done without intermediate objects, if you are absolutely sure that the two strings contain only Latin characters:

bool latinCompare(const QString& qstr, const std::string& str)
{
  if( qstr.length() != (int)str.size() )
    return false;
  const QChar* qstrData = qstr.data();
  for( int i = 0; i < qstr.length(); ++i ) {
    if( qstrData[i].toLatin1() != str[i] )
      return false;
  }
  return true;
}

Otherwise you should decode the std::string into a QString and compare the two QStrings.

Dan Milburn
  • 5,600
  • 1
  • 25
  • 18
  • 1
    So instead converting the whole string at once, you do the conversion via toLatin1() char by char. I'd assume that's less efficient, but if anyone cares to profile it, I'd be interested in numbers. – Frank Osterfeld Aug 14 '13 at 12:41
  • Looking at toLatin1_helper in qstring.cpp, the full string conversion has to iterate over every char in the string anyway, plus allocating a QByteArray. On the other hand, the equality check is then a memcmp, and there is an optimised path for SSE2 which would make a difference (this is in 4.7.2 which is what I have handy so might have changed). My version can be optimised by using QString::data() to get a QChar*. I was mostly trying to meet the goal of avoiding temporary allocations, but I have no idea if that would be faster in this case. – Dan Milburn Aug 14 '13 at 12:56