来自std :: string的高效QVariant构造

时间:2014-04-15 19:02:18

标签: c++ qt c++11

我正在尝试确定从std :: string构造QVariant的最有效方法,并让它存在于std :: vector中。我现在正在做:

std::string foo = "test";
std::vector<QVariant> variants;
...
variants[0] = QString::fromStdString(foo);

这种方法似乎构造了一个临时的QString,然后在调用QVariant(const QString &) c'tor后销毁它。

有什么方法可以避免临时QString?

3 个答案:

答案 0 :(得分:8)

register std::string类型,然后转换为QString将会过时。

// in some header file
Q_DECLARE_METATYPE (std::string)

// in main function
qRegisterMetaType<std::string>("std::string");

答案 1 :(得分:2)

如果你确实想存储QString,那么由于Qt的写时复制语义,临时QString对象与性能无关。从std::stringQString进行文本解码将占主导地位,并且由于COW无论如何都不会复制数据(除非修改)。如果std::string'\0' - 已终止的文字,则您只需使用this QVariant constructor,这可能与QString的最佳效果相同:

variants.emplace(0, QVariant(stdstr.c_str());

替代解决方案是将std::string存储为QByteArray而不是QString。如果需要复制std::string数据,您需要决定的一件事是。如果您知道指向字符串数据的指针在QByteArray的生命周期内仍然有效,则可以使用this

// warning, does not copy string data, so pointer to it must remain valid
variants.emplace(0, QByteArray::fromRawData(stdstr.data(), stdstr.size()));

更安全是this,它复制但没有文字解码:

variants.emplace(0, QByteArray(stdstr.data(), stdstr.size()));

请注意std::string并不关心编码,而是8位,所以实际上QByteArray是它的Qt对应物。 QString在内部存储Unicode文本UTF-16,因此无论std::string内容的编码如何,都始终需要进行转换。

此外,您应该阅读std::string::data()std::vector::emplace()个引用。

答案 2 :(得分:1)

  

有什么方法可以避免临时QString?

疑。

即使将QString传递给QVariant构造函数,它也会复制。

但它并不重要,因为QStrings是隐含共享的,所以复制它们是O(1)操作

虽然您可以将字符串存储为void*,但如果您需要,它不会自动转换为字符串。