如何在没有副本的情况下从QByteArray“窃取”数据

时间:2015-06-28 13:05:41

标签: qt

是否可以将指针指向QByteArray的内部T* data并销毁QByteArray本身,以便指针保持未发布状态?我想在类似于以下场景的事情中使用它:

const char* File::readAllBytes(const String& path, u64& outCount) {
    QFile file(*static_cast<QString*>(path.internal()));
    outCount = static_cast<u64>(file.size());
    if (!file.open(QIODevice::ReadOnly)) gException("Failed to open file");
    const QByteArray array = file.readAll();
    return array.steal();
}

2 个答案:

答案 0 :(得分:3)

不,你不能窃取QByteArray的指针,除非它是用QByteArray::fromRawData构建的,事实并非如此。但是,您可以手动创建char数组,并使用QFile::read(char * data, qint64 maxSize)从文件中读取数据。然后,您将决定将指针传递到何处以及何时传递到delete[]

请注意,这不是一种好习惯。您应该尽可能使用托管分配,并且Qt提供足够的覆盖大多数可能的用例。除非你试图做一些非常低级的事情,否则你不应该这样做。

请注意,许多Qt类(包括QStringQByteArray)都使用写时复制策略,因此您通常不应该害怕复制它们并将它们传递给另一个上下文。

答案 1 :(得分:0)

不,但您可以通过不使用QByteArray

轻松回避问题
const char* File::readAllBytes(const String& path, u64& outCount) {
    QFile file(*static_cast<QString*>(path.internal()));
    if (!file.open(QIODevice::ReadOnly)) return nullptr;
    auto N = file.bytesAvailable();
    char *data = malloc(N);
    outCount = file.read(data, N);
    return data;
}

上述解决方案还假设数据的使用者知道需要free数据。

唉,使用这种API调用的手动内存管理是一个坏主意。如果您不希望在API中使用Qt类,则应使用std::vector<char>代替:

std::vector<char> File::readAllBytes(const String& path) {
    std::vector<char> result;
    QFile file(*static_cast<QString*>(path.internal()));
    if (!file.open(QIODevice::ReadOnly)) return result;
    result.resize(file.bytesAvailable());
    auto count = file.read(result.data(), result.size());
    result.resize(count);
    return result;
}

我觉得String是某种与框架无关的字符串包装器。也许您可以在std::u16string上安置与QString相同的UTF16数据。