【问题标题】:efficient QVariant construction from a std::string来自 std::string 的高效 QVariant 构造
【发布时间】:2014-04-15 19:02:18
【问题描述】:

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

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

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

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

【问题讨论】:

  • variants.emplace(QString::fromStdString(foo)), variants.push_back(QString::fromStdString(foo))?
  • 那个临时字符串的数据实际上是活得很好——它的私有数据存在于变体中。被销毁的临时对象是一个非常轻量级的外壳。

标签: c++ qt c++11


【解决方案1】:

register std::string 类型,然后转换为QString 将被废弃。

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

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

【讨论】:

  • 这是在 QVariant 中存储 std::string 的正确方法,但我认为无论如何都会涉及多个副本,所以我怀疑会有显着的收益。
  • std::string 也使用写时复制模式。您还可以避免代价高昂的conversion,因为甚至涉及codec 方法。
  • IIRC std::string 由于更严格的线程安全要求,不太可能在新版本的标准中使用 COW。 OTOH,关于编解码器转换的观点肯定是相关的,因为QString 在 UTF-16 中工作。
【解决方案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() 参考资料。

【讨论】:

    【解决方案3】:

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

    怀疑。

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

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

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

    【讨论】:

    • 这是错误的。没有副本。复制仅在写入时发生,我不知道您在这里所说的 O(1) 是什么意思。这不是算法,即使是,对于字符串中的“n”个元素,它也是“O(n)”。
    • 我使用的是 C++ 的拷贝定义:调用拷贝构造函数。
    猜你喜欢
    • 2016-04-04
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    相关资源
    最近更新 更多