将对以字符串形式返回文件内容的函数执行移动语义优化或返回值优化,我会从中受益吗

Would I benefit from applying move semantic or return-value-optimization will be performed for function that returns file content as string?

本文关键字:优化 返回值 语义 移动 执行 字符串 返回 文件 函数      更新时间:2023-10-16

我有一些load(..)方法,它将文件的内容加载到std::wstring中。它通常处理相当大的文件(高达几MB),我广泛使用它,所以我寻找优化的可能性(既不破坏"将文件内容加载到字符串中"的简单性,也不产生对其他库的额外依赖)。

我应该在这里使用move语义吗(我不太熟悉)?或者,由于编译器将执行的返回值优化,我编写它的方式接近于最佳时间?

inline static std::wstring load(std::wstring filePath) {
    std::wifstream file(filePath.c_str());
    if(file){
        std::wstring fileString;
        fileString.reserve((size_t)file.tellg());
        file.seekg(0);
        while(!file.eof()){
            fileString += file.get();
        }
        file.close();
        return fileString;
    }
    file.close();
    ERROR_HANDLE(L"File could not be open:n" + filePath);
    return L"";
}

实现的代码将继续为存储文件内容的字符串分配新的内存。对于引用的字符串大小,实际分配开销可能可以忽略不计。然而,内存很有可能没有映射到任何缓存,因此访问它可能相对昂贵:已经映射的内存需要收回。假设调用load()的代码本质上只处理字符串的内容,那么保持相同的字符串可能具有性能优势。相应的实现可能如下所示:

inline bool load(std::string const& path, std::wstring& content) {
    std::wifstream in(path.c_str());
    if (in) {
        content.assign(std::istreambuf_iterator<wchar_t>(in),
                       std::istreambuf_iterator<wchar_t>());
        return true;
    }
    else {
        return false;
    }
}

应该不需要reserve()内存,因为content应该快速确定足够处理文件的容量。

坚持原始接口,即返回字符串,无论如何都很容易移动字符串:当返回临时对象或命名变量时,将使用移动构造函数。理想情况下,也可以通过为复制省略制定可行的实现来避免移动。例如,您可以始终返回相同的对象。复制省略通常发生在没有实现右值引用的编译器或没有移动构造函数的类中。我会这样实现你的功能:

inline std::wstring load(const std::string& path) {
    std::wifstream in(path.c_str());
    std::wstring   result;
    if (in) {
        // possibly result.reserve() capacity
        result.assign(std::istreambuf_iterator<wchar_t>(in),
                      std::istreambuf_iterator<wchar_t>());
    }
    return result;
}